"< 액세스 수정자 (access modifiers)> 에 대해 말씀드리겠습니다 . 이전에 한 번 말씀드렸지만 반복은 학습의 기둥입니다."
다른 클래스가 클래스의 메서드 및 변수에 대해 갖는 액세스(가시성)를 제어할 수 있습니다. 액세스 수정자는 «누가 이 메소드/변수에 액세스할 수 있습니까?»라는 질문에 답합니다. 각 메소드 또는 변수에 대해 하나의 수정자만 지정할 수 있습니다.
1) « 공개 » 수식어.
public 한정자 로 표시된 변수, 메서드 또는 클래스는 프로그램의 어디에서나 액세스할 수 있습니다. 이것은 최고 수준의 개방성입니다. 제한이 없습니다.
2) « 개인 » 수식어.
private 한정자 로 표시된 변수, 메서드 또는 클래스는 선언된 클래스에서만 액세스할 수 있습니다. 표시된 메서드 또는 변수는 다른 모든 클래스에서 숨겨집니다. 이것은 가장 높은 수준의 개인 정보 보호입니다. 학급에서만 액세스할 수 있습니다. 이러한 메서드는 상속되지 않으며 재정의할 수 없습니다. 또한 하위 클래스에서 액세스할 수 없습니다.
3) « 기본 수정자».
변수나 메서드가 수정자로 표시되지 않은 경우 "기본" 수정자로 표시된 것으로 간주됩니다. 이 한정자가 있는 변수 및 메서드는 선언된 패키지의 모든 클래스와 해당 클래스에만 표시됩니다. 이 수정자는 " 패키지 " 또는 " 패키지 전용 " 액세스 라고도 하며 변수 및 메서드에 대한 액세스가 클래스를 포함하는 전체 패키지에 대해 열려 있다는 사실을 암시합니다.
4) « 보호된 » 수정자.
이 액세스 수준은 패키지 보다 약간 더 넓습니다 . protected 한정자 로 표시된 변수, 메서드 또는 클래스는 해당 패키지(예: "패키지") 및 모든 상속된 클래스에서 액세스할 수 있습니다.
이 표는 모든 것을 설명합니다.
가시성 유형 | 예어 | 입장 | |||
---|---|---|---|---|---|
당신의 수업 | 귀하의 패키지 | 후손 | 모든 수업 | ||
사적인 | 사적인 | 예 | 아니요 | 아니요 | 아니요 |
패키지 | (수정자 없음) | 예 | 예 | 아니요 | 아니요 |
보호 | 보호 | 예 | 예 | 예 | 아니요 |
공공의 | 공공의 | 예 | 예 | 예 | 예 |
이 표를 쉽게 기억할 수 있는 방법이 있습니다. 당신이 유언장을 쓰고 있다고 상상해보십시오. 모든 것을 네 가지 범주로 나누고 있습니다. 누가 당신의 물건을 사용합니까?
액세스 권한이 있는 사람 | 수식어 | 예 |
---|---|---|
나만 _ | 사적인 | 개인 저널 |
가족 | (수정자 없음) | 가족 사진 |
가족 및 상속인 | 보호 | 가족 재산 |
여러분 | 공공의 | 논문집 |
"동일한 패키지의 클래스가 한 가족의 일부라고 상상하는 것과 같습니다."
"또한 재정의 방법에 대한 몇 가지 흥미로운 뉘앙스를 알려 드리고 싶습니다."
1) 추상 메서드의 암시적 구현.
다음 코드가 있다고 가정해 보겠습니다.
class Cat
{
public String getName()
{
return "Oscar";
}
}
그리고 이 클래스를 상속하는 Tiger 클래스를 만들고 새 클래스에 인터페이스를 추가하기로 결정했습니다.
class Cat
{
public String getName()
{
return "Oscar";
}
}
interface HasName
{
String getName();
int getWeight();
}
class Tiger extends Cat implements HasName
{
public int getWeight()
{
return 115;
}
}
IntelliJ IDEA에서 구현하라고 지시한 누락된 메서드를 모두 구현하기만 하면 나중에 버그를 찾는 데 오랜 시간을 소비하게 될 수 있습니다.
Tiger 클래스에는 Cat에서 상속된 getName 메서드가 있으며 이는 HasName 인터페이스에 대한 getName 메서드의 구현으로 간주됩니다.
"나는 그것에 대해 끔찍한 것을 보지 않습니다."
"그렇게 나쁘지는 않습니다. 실수가 스며들기 쉬운 곳입니다."
그러나 더 나빠질 수 있습니다.
interface HasWeight
{
int getValue();
}
interface HasSize
{
int getValue();
}
class Tiger extends Cat implements HasWeight, HasSize
{
public int getValue()
{
return 115;
}
}
여러 인터페이스에서 항상 상속할 수는 없는 것으로 나타났습니다. 보다 정확하게는 상속할 수는 있지만 올바르게 구현할 수는 없습니다. 예를 보십시오. 두 인터페이스 모두 getValue() 메서드를 구현해야 하지만 반환해야 하는 항목(무게 또는 크기)이 명확하지 않습니다. 이것은 처리해야 하는 것이 상당히 불쾌합니다.
"동의합니다. 메소드를 구현하고 싶지만 할 수 없습니다. 기본 클래스에서 동일한 이름을 가진 메소드를 이미 상속받았습니다. 고장났습니다."
"하지만 좋은 소식이 있습니다."
2) 가시성 확대. 유형을 상속하면 메소드의 가시성을 확장할 수 있습니다. 다음과 같이 표시됩니다.
자바 코드 | 설명 |
---|---|
|
|
|
protected 메서드의 가시성을 에서 로 확장했습니다 public . |
암호 | 이것이 "합법적"인 이유 |
---|---|
|
모든 것이 훌륭합니다. 여기서 우리는 자손 클래스에서 가시성이 확장되었다는 사실조차 알지 못합니다. |
|
여기에서는 가시성이 확장된 메서드를 호출합니다.
이것이 가능하지 않은 경우 Tiger에서 항상 메소드를 선언할 수 있습니다. 즉, 보안 위반에 대해 말하는 것이 아닙니다. |
|
기본 클래스( Cat ) 에서 메서드를 호출하는 데 필요한 모든 조건이 충족되면 자손 유형( Tiger ) 에서 메서드를 호출하는 데 필요한 모든 조건이 충족됩니다 . 메서드 호출에 대한 제한이 강하지 않고 약했기 때문입니다. |
"내가 완전히 이해했는지 확신할 수 없지만 이것이 가능하다는 것을 기억할 것입니다."
3) 반환 유형을 좁히십시오.
재정의된 메서드에서 반환 형식을 좁은 참조 형식으로 변경할 수 있습니다.
자바 코드 | 설명 |
---|---|
|
|
|
우리는 메서드를 재정의했으며 getMyParent 이제 Tiger 객체를 반환합니다. |
암호 | 이것이 "합법적"인 이유 |
---|---|
|
모든 것이 훌륭합니다. 여기서 우리는 getMyParent 메서드의 반환 유형이 자손 클래스에서 확장되었다는 사실조차 알지 못합니다.
«오래된 코드»가 작동하고 작동하는 방식. |
|
여기서 반환 유형이 축소된 메서드를 호출합니다.
이것이 가능하지 않은 경우 항상 Tiger에서 메소드를 선언할 수 있습니다. 즉, 보안 위반 및/또는 유형 캐스팅 위반이 없습니다. |
|
변수의 유형을 기본 클래스(Cat)로 확장했지만 여기에서는 모든 것이 잘 작동합니다.
재정의로 인해 올바른 setMyParent 메서드가 호출됩니다. 그리고 getMyParent 메소드를 호출할 때 걱정할 것이 없습니다 . Tiger 클래스의 반환 값이 문제 없이 여전히 기본 클래스(Cat) 의 myParent 변수에 할당 될 수 있기 때문입니다. Tiger 개체는 Tiger 변수와 Cat 변수 모두에 안전하게 저장할 수 있습니다. |
"네. 알겠습니다. 메서드를 재정의할 때 기본 클래스만 처리할 수 있고 클래스에 대해 아무것도 모르는 코드에 개체를 전달하는 경우 이 모든 것이 어떻게 작동하는지 알아야 합니다. "
"정확합니다! 그렇다면 중요한 질문은 메서드를 재정의할 때 반환 값의 유형을 좁힐 수 없는 이유는 무엇입니까?"
"이 경우 기본 클래스의 코드가 작동을 멈출 것이 분명합니다."
자바 코드 | 문제에 대한 설명 |
---|---|
|
|
|
우리는 getMyParent 메서드를 오버로드하고 반환 값의 유형을 좁혔습니다.
여기 모든 것이 괜찮습니다. |
|
그런 다음 이 코드는 작동을 멈춥니다.
getMyParent 메소드는 실제로 Tiger 객체에서 호출되기 때문에 객체의 모든 인스턴스를 반환할 수 있습니다. 그리고 우리는 과제 전에 수표가 없습니다. 따라서 Cat 유형 myParent 변수가 String 참조를 저장하는 것이 전적으로 가능합니다. |
"훌륭한 예입니다, 아미고!"
Java에서는 메서드가 호출되기 전에 개체에 해당 메서드가 있는지 여부를 확인하지 않습니다. 모든 검사는 런타임에 발생합니다. 그리고 누락된 메서드에 대한 [가상] 호출은 프로그램이 존재하지 않는 바이트코드를 실행하려고 시도하게 할 가능성이 높습니다. 이것은 궁극적으로 치명적인 오류로 이어지고 운영 체제는 프로그램을 강제로 종료합니다.
"워. 이제 알겠어."
GO TO FULL VERSION