"안녕하세요, 아미고! 오늘 수업의 주제는 유형 변환 확대 및 축소입니다. 오래 전에 기본 유형 확대 및 축소에 대해 배웠습니다. 레벨 10에서. 오늘 우리는 참조 유형, 즉 참조 유형에 대해 어떻게 작동하는지에 대해 이야기할 것입니다. 클래스의 인스턴스."

사실, 모든 것이 아주 간단합니다. 클래스의 상속 체인을 상상해 보십시오. 클래스, 부모, 부모의 부모 등이 Object 클래스까지 거슬러 올라갑니다. 클래스는 상속받은 클래스의 모든 멤버 메서드를 포함하기 때문에 클래스 의 인스턴스는 부모의 유형인 변수에 저장할 수 있습니다 .

예를 들면 다음과 같습니다.

암호 설명
class Animal
{
public void doAnimalActions();
}class Cat extends Animal
{
public void doCatActions();
}class Tiger extends Cat
{
public void doTigerActions();
}
여기에는 Animal, Cat 및 Tiger의 세 가지 클래스 선언이 있습니다. 고양이는 동물을 물려받습니다. 그리고 Tiger는 Cat을 물려받습니다.
public static void main(String[] args)
{
Tiger tiger = new Tiger();
Cat cat = new Tiger();
Animal animal = new Tiger();
Object obj = new Tiger();
}
Tiger 개체는 항상 조상 중 하나의 유형인 변수에 할당될 수 있습니다. Tiger 클래스의 경우 Cat, Animal 및 Object입니다.

이제 확장 및 축소 변환을 살펴보겠습니다.

할당 작업으로 인해 상속 체인 위로(Object 클래스 쪽으로) 이동하게 되면 확장 변환(업캐스팅이라고도 함)을 처리하고 있는 것입니다. 객체 유형을 향해 사슬 아래로 이동하면 축소 변환(다운캐스팅이라고도 함)입니다.

상속 체인을 위로 이동하는 것을 확장이라고 합니다. 더 일반적인 유형으로 이어지기 때문입니다. 그러나 이렇게 하면 상속을 통해 클래스에 추가된 메서드를 호출할 수 있는 기능을 잃게 됩니다.

암호 설명
public static void main(String[] args)
{
Object obj = new Tiger();
Animal animal = (Animal) obj;
Cat cat = (Cat) obj;
Tiger tiger = (Tiger) animal;
Tiger tiger2 = (Tiger) cat;
}
유형을 좁힐 때 유형 변환 연산자를 사용해야 합니다. 즉, 명시적 변환을 수행합니다.

이로 인해 Java 시스템은 객체가 변환하려는 유형을 실제로 상속하는지 여부를 확인합니다.

이 작은 혁신으로 유형 캐스팅 오류 수가 크게 감소했으며 Java 프로그램의 안정성이 크게 향상되었습니다.

암호 설명
public static void main(String[] args)
{
Object obj = new Tiger();
if (obj instanceof Cat)
{
Cat cat = (Cat) obj;
cat.doCatActions();
}}
더 좋은 방법은  instanceof 검사를 사용하는 것입니다.
public static void main(String[] args)
{
Animal animal = new Tiger();
doAllAction(animal);

Animal animal2 = new Cat();
doAllAction(animal2);

Animal animal3 = new Animal();
doAllAction(animal3);
}

public static void doAllAction(Animal animal)
{
if (animal instanceof Tiger)
{
Tiger tiger = (Tiger) animal;
tiger.doTigerActions();
}

if (animal instanceof Cat)
{
Cat cat = (Cat) animal;
cat.doCatActions();
}

animal.doAnimalActions();
}
그리고 여기에 그 이유가 있습니다. 왼쪽의 예를 살펴보십시오.

우리(우리의 코드)는 어떤 유형의 객체로 작업하고 있는지 항상 알지 못합니다. 변수(Animal)와 동일한 유형의 개체이거나 모든 자손 유형(Cat, Tiger)일 수 있습니다.

doAllAction 메소드를 고려하십시오. 전달된 개체 유형에 관계없이 올바르게 작동합니다.

즉, Animal, Cat 및 Tiger의 세 가지 유형 모두에 대해 올바르게 작동합니다.

public static void main(String[] args)
{
Cat cat = new Tiger();
Animal animal = cat;
Object obj = cat;
}
여기에 세 가지 할당 작업이 있습니다. 그들 모두는 확대 전환의 예입니다.

검사가 필요하지 않기 때문에 여기에는 유형 캐스트 ​​연산자가 필요하지 않습니다. 객체 참조는 항상 조상 중 하나인 유형의 변수에 저장될 수 있습니다.

"아, 마지막에서 두 번째 예는 모든 것을 명확하게 했습니다. 검사가 필요한 이유와 유형 변환이 필요한 이유입니다."

"그렇기를 바랍니다. 이 사실에 주의를 기울이고 싶습니다."

이 중 어느 것도 개체를 어떤 식으로든 변경하지 않습니다! 유일한 변경 사항은 특정 참조 변수에서 호출 할 수 있는

예를 들어 Cat 변수를 사용하면 doAnimalActions 및 doCatActions 메서드를 호출할 수 있습니다. Tiger 개체를 가리키더라도 doTigerActions 메서드에 대해 아무것도 모릅니다.

"네, 알겠습니다. 생각보다 쉬웠습니다."