Sobes.tech
Junior

Czym jest modyfikator dostępu 'protected' w języku programowania i w jakich przypadkach należy go używać?

sobes.tech AI

Odpowiedź od AI

protected — jest modyfikatorem dostępu, który pozwala członkom klasy (pola, metody) być dostępnymi wewnątrz samej klasy, w klasach dziedziczących (nawet jeśli znajdują się w innym pakiecie) oraz we wszystkich klasach tego samego pakietu.

Zastosowanie:

Używa się go, gdy chce się zapewnić dostęp do członków klasy tylko jej dziedzicom i innym klasom w tym samym pakiecie, ukrywając je przed światem zewnętrznym poza tym pakietem i hierarchią dziedziczenia.

Przykłady scenariuszy użycia:

  • Gdy klasa bazowa zawiera pola lub metody będące częścią jej wewnętrznej implementacji, ale są niezbędne do rozszerzenia funkcjonalności w klasach dziedziczących.

    public class Animal {
        protected String name; // Dostępne dla dziedziców i klas w tym samym pakiecie
    
        protected void eat() { // Dostępne dla dziedziców i klas w tym samym pakiecie
            System.out.println(name + " je.");
        }
    }
    
    public class Dog extends Animal {
        public void bark() {
            System.out.println(name + " szczeka."); // Dostęp do pola protected name
            eat(); // Dostęp do metody protected eat()
        }
    }
    
  • Gdy w pakiecie znajduje się grupa klas ściśle ze sobą powiązanych i konieczne jest, aby miały dostęp do elementów wewnętrznych siebie nawzajem, ale ukrywały te elementy przed klasami z innych pakietów. W tym przypadku protected działa podobnie do modyfikatora domyślnego (package-private) dla klas w tym samym pakiecie, ale dodatkowo otwiera dostęp dla dziedziczących z dowolnego pakietu.

    // Pakiet com.example.core
    package com.example.core;
    
    public class BaseConfig {
        protected int threshold = 10; // Dostępny dla klas w com.example.core i dziedziczących z dowolnego pakietu
    }
    
    // Pakiet com.example.app (może być w innym pakiecie)
    package com.example.app;
    
    import com.example.core.BaseConfig;
    
    public class AppConfig extends BaseConfig {
        public void displayThreshold() {
            System.out.println("Próg: " + threshold); // Dostęp do pola protected z innego pakietu
        }
    }
    
    // Pakiet com.example.core
    package com.example.core;
    
    public class RelatedConfig {
         public void printBaseThreshold(BaseConfig config) {
             System.out.println("Podstawowy próg z RelatedConfig: " + config.threshold); // Dostęp do pola protected w tym samym pakiecie
         }
    }
    

Unikaj nadmiernego używania protected, ponieważ może to utrudnić refaktoryzację i naruszyć enkapsulację, pozwalając dziedzicom lub klasom w tym samym pakiecie na bezpośrednią manipulację stanem wewnętrznym obiektu. Lepszym rozwiązaniem jest użycie private z publicznymi metodami getter/setter, jeśli bezpośrednie dziedziczenie i dostęp do wewnętrznej implementacji nie są głównym celem.