오키최고
10
2021-09-15 00:25:28
3
231

다형성에관한 질문을 드립니다.


현재 다형성과 관련해서 및 downcating을 공부하고 있습니다. 이게 사용방법은 숙지한것 같은데 그냥 외운것이지 개념적으로 이해가 안가서 문의드립니다.

예제로 본 것이 아래 자바 코드입니다. 

여기서 이해가 안가는점은 왜 food.print를 해서 굳이 Food class 의 print를 출력하는지 모르겠습니다. 그냥 Food.print 하면 안되나요? 즉 upcasting과 downcasting 의 존재 이유를 모르겠습니다. 어떤경우에 필요해서 사용하는것인지 알고 싶습니다.

제가 인터넷에 본 답변은 "즉 뭘 넣을지모르니까 최고 부모인 Object형에는 다 들어갈 수 있어서 이런식으로 선언해놓는 겁니다." 라는 답변을 보았는데 이것은 upcasting 예기인것 같고 결국 부모 Object로 자식 Object내용을 이용하고자 함인것 같은데요.


그럼 downcast는 어떻게 이해를 해야 되나요?

Upcast와 Downcast를 어떤 개념으로 받아드려야할지 몰라 도움 부탁드립니다.




class Food

{

    void print()

    {

       System.out.println("Food");

    }

}

 

 

class SeaFood extends Food

{

    void print()

    {

       System.out.println("SeaFood");

    }

}

 

 

 

class DownCast

{

   public static void main(String[] args)

   {

       Food food = new SeaFood(); //UpCasting - 상위 Food에 하위 SeaFood를 담음(자동 형 변환)

       SeaFood sea_food = (SeaFood)food; //DownCasting - 하위 SeaFood에 상위 Food를 담음(명시적 형 변환)

       sea_food.print(); //SeaFood class의 print 출력

   }

}


0
  • 답변 3

  • 감쟈아
    7
    2021-09-15 01:55:27 작성 2021-09-15 02:03:15 수정됨

    Food var = new SeaFood();

    이러한 형식으로 하위객체가 업캐스팅 되어 선언되면 var의 타입은 상위객체 이기때문에 하위 객체의 특성을 이용할 수 없습니다.

    예를들어 하위객체인 SeaFood에 print2()라는 메소드가 정의되어있어도 var은 print()2라는 메소드를 사용할 수 없습니다.

    이때 다운캐스팅을 통해 다시 참조변수 var의 타입을 하위객체인 SeaFood로 변경하게되면 다시 SeaFood만의 특성인 print2() 라는 메소드를 사용할 수 있게되는데 이러한 코드를 작성해야할 경우 다운캐스팅을 하게됩니다.

    다운캐스팅을 이해하려면 위의 코드 보다는 

    public class Cast {
        public static void main(String[] args) {
            Food food = new SeaFood();
            
            fish.eat(); // 업캐스팅 되어 선언되었기때문에 SeaFood의 특성인 eat사용 불가 Error !
            
            SeaFood fish = (SeaFood) food;
            fish.eat(); // 다운캐스팅 되어 SeaFood의 특성이 사용가능해짐
        }
    }
    
    class Food {
        public void print() {
            System.out.println("This is Food");
        }
    }
    
    class SeaFood extends Food {
        
        public void eat() {
            System.out.println("eat !");
        }
        
        @Override
        public void print() {
            System.out.println("This is SeaFood");
        }
    }

    이 코드가 좀더 이해하는데 도움이 되지 않을까 싶네요



  • 이집코드재밌네
    37
    2021-09-15 02:36:22 작성 2021-09-15 02:40:25 수정됨

    다형성의 참조변수의 형변환을 쓰는 이유는 참조변수가 가르키고 있는 객체의 사용할 수 있는 멤버의 개수를 조절하기 위해서 입니다.

    조상 클래스를 상속받은 자손 클래스는 조상 클래스의 모든 멤버를 상속받고 +자신이 추가한 멤버를 추가로 갖기 때문에 자손 클래스의 총 멤버의 개수는 최소 조상 클래스와 같거나 (따로 추가한 멤버가 없을 경우) 많게 됩니다.

    그런데 여기서 자손 클래스 타입의 객체를 가르키고 있는 참조변수의 타입을 조상 타입으로 업캐스팅 하게 되면 가르키고 있는 객체는 자손 클래스 타입의 객체일지라도 사용할 수 있는 멤버는 조상 클래스에 명시된 멤버만 사용 가능할 수밖에 없게 됩니다.

    이를 실생활의 예로 찾아보면 마치 구형 TV의 리모컨으로 스마트 TV를 조작하는 것과 같은 상황이 됩니다. 스마트 TV는 여러가지 기능을 포함하고 있지만 리모컨이 구형 TV용이라 제 기능을 다 못쓰게 되는 상황인거죠. 

    왜 굳이 이렇게까지 할 필요가 있느냐 싶지만 이러한 다형성의 특징은 재사용성과 호환성을 높이는 효과를 가져옵니다. 예를들면 구형 TV를 스마트 TV로 교체했지만 사용하던 구형 TV 리모컨이 스마트TV에 잘 작동 하는 것처럼요.

    추가로 설명하자면 업캐스팅의 경우 참조변수가 다룰 수 있는 멤버의 개수가 실제 객체가 갖고 있는 멤버의 갯수보다 적을 것이 분명하기 때문에 문제가 되지 않으므로 본문의 Food food = new SeaFood(); (원래는 Food food = new (Food)SeaFood(); ) 처럼 형변환 연산자가 생략되는 자동 형변환이 가능하지만,

    반대인 다운캐스팅의 경우 참조변수가 다룰 수 있는 멤버의 개수를 늘리는 것이고 실제 객체의 멤버 갯수 보다 참조변수가 사용할 수 있는 멤버의 개수가 많아지는 문제가 발생할 가능성이 존재하기 때문에 형변환 연산자를 생략할 수 없는 것입니다.

    그래서 참조변수의 형변환을 사용할 때는 참조변수가 가르키는 객체의 타입이 무엇인지 instanceof 연산자를 사용해서 미리 확인하는 것이 안전합니다.

  • yeori
    2k
    2021-09-15 08:33:19

    예제가 부적절해서 다형성의 필요성을 보여주는데 적합하지 않습니다.

    위 예제는 다형성 관련 문법만 보여주는 용도입니다.

    그러니까 위 예제를 갖고 왜 다형성이 필요한가, 유용한가 보여주기에는 부족합니다.

    다형성같은 개념은 코드를 많이 작성해보면 자연스럽게 이해하게 됩니다. 경험이 필요하고 이 경험 부족을 이론으로만 채우려고 하면 겉돌게 됩니다.

    그리고 당장 이해가 안된다고 코드를 못짜는것도 아닙니다.

  • 로그인을 하시면 답변을 등록할 수 있습니다.