인스턴스변수는 오버라이딩 대상이 아니다
다형성
먼저, Head First Java 책의 예제를 이용한다.
위의 사진처럼 상속을 이용하여 코딩을 했다고 가정하자.
- Animal 클래스
- 하위 클래스들
맨위의 예제와 같이 위와 같은 클래스들을 구성해보았다.
이제 다형성을 증명하기 위해 메인클래스에서 다음과 같이 실행해준다.
최상위 클래스에서 이미 정의한 메소드를 하위 클래스에서 재정의하여 사용했다. (오버라이딩)
그후 Animal은 자식클래스에서 재정의된 메소드를 호출했다.
아래의 코드를 살펴보자.
Animal w = new Lion();
Animal타입으로 Lion객체를 생성했다.
그후 실행결과로 보면 Lion 클래스에 있는 메소드를 직접가져와 사용했다.
예를들어,
Animal w = new Hippo();
Animal w = new Cat();
Animal w = new Tiger();
이것처럼, 하나의 객체가 여러 가지 타입을 가질 수 있는 것 또는
하나의 타입으로 여러 종류의 객체를 여러 가지 모습으로 해석하는것 이것을 다형성이라고 부른다
상속에 관해 코멘트를 덧붙이면 상위 클래스에는 없는 메소드를 하위 클래스에서 정의하여 쓴다면
바람직한 프로그램이 아니다. 또한 상속클래스는 최대 하위클래스를 두개까지 만들어 두는게 좋다.
이중상속이 가능할까?
위 사진처럼 만약 하위클래스에서 요구하는 메소드가 있을때 상위 클래스 두개 모두 해당 메소드가 있으면 어떤 것을 써야할지 모르기 때문에 불가능하다
특정 클래스에만 새로운 메서드를 추가하고 싶다면?
void beFriendly();와 같은 반려동물을 표현하기위한 메서드를 추가할 때
위의 그림처럼 Cat과 Dog에 가장 효율적으로 넣을수 있는 방법이 무엇일까?
제일 상위클래스에 해당 메서드를 추가해주는 방법은 가장 간단해보이지만 다른 하위클래스들에게 어찌됐건
해당 메서드를 상속시켜주는 것이니 비효율적으로 보인다.
그렇다면, 해당클래스에만 새로운 메서드를 추가하는건?
모든 프로그래머가 지금 그리고 미래에 계획안에 관해 해당 클래스에만 들어가야할 정보를 알아야할 필요가 있어서
비효율적이다.
그렇다면 최상위 클래스를 추가하는건?
다형성이 깨져버려 말이되지 않는다. 예를들어 Animal에 있는 메소드를 Dog에게 상속하여 오버라이딩 했을때,
Animal a=new Dog(); 을 하고 a의 모든메서드를 실행시키면 Animal에는 없지만 Pet에만 있는 메서드가 있기에
실행되지 않는다.
인터페이스
이럴때 필요한것이 인터페이스이다.
Pet을 똑떼서 인터페이스로 구현하는 것이다.
인터페이스는 해당 내용을 덧붙일 클래스에 emplement로 적어놓는다
ex)public class Dog extends Canine implements Pet
또한 인터페이스 안의 메소드 들은 무조건 추상적이여야하며, body가 없어야한다.
여기서 팁하나가 있다면 bin폴더에 해당 Pet파일을 찾아가보면 Pet.class로 저장되어 있는것을 볼수있다.
결국 인터페이스도 .class로 저장된다.
.Super
super 키워드는 부모 클래스로부터 상속받은 필드나 메소드를 자식 클래스에서 참조하는 데 사용하는 참조 변수이다.
위와 같이 .super 변수를 사용하면 부모클래스에 접근할수있다.
.this
여기서 setAge의 인자 int a 를 필드의 age와 이름을 같게 하려면 어떻게 해야할까?
이렇게 사용하면 메서드의 인자에 필드와 같은 이름을 붙여도 구분하여 사용할수 있다.
즉,this는 주로 생성자와 메소드의 매개변수 이름이 필드와 동일한 경우, 인스턴스 멤버인 필드임을 명시할때 사용한다.
위에서 this.age는 필드인 age를 의미한다. 달리말해 this뒤의 변수명은 인수가 아닌 필드를 의미한다
리스트에 객체를 넣고 해당 객체의 메서드를 실행시키는 프로그램
<Animal>타입의 animals 리스트를 생성하고 순서대로 Dog,Cat객체를 담은뒤 for문을 이용하여 해당객체의 메서드를 실
행시킨 프로그램이다.
이것을 조금만 변형해본다.
밑에 잘려서 실행결과가 덜 나왔지만 대충 위와같이 나온다.
위의 예제는 Injection 클래스에 있는 shotAnimal 메서드를 이용하여 "주사를 놓습니다" 코멘트와 각각의 makenoise()를
출력해준다.
궁금사항)
위에서 animals.get(0) 을 그냥 찍어보면 Animal()이 출력된다.
이는 ArrayList<Object>를 사용할 때 get()메서드는 Object유형을 반환하는데 컴파일러는 객체가 객체로부터 상속받는
것만 알고있으며 그게 <Dog>인지는 모르기 때문이다.
그래서 Dog이 상속받는 최상위 클래스 Animal가 출력되는 것인가?
만약 그렇다면 위의 변형예제
여기서 in.shotAnimal안의 변수 animals.get(i)는 내부적으로는 각각의 (Dog,Cat등) 객체이고 외부적으로 찍히는건 그저
Animal()인 것인가?
의문사항해결
ArrayList<Dog> myDogarrayList = new ArrayList<Dog>();
Dog aDog = new Dog();
myDogArrayList.add(aDog);
Dog d = myDogArrayList.get(0) -> Dog객체?;
위는 Dog객체를 보유한 ArrayList를 선언하고 Dog객체를 만든뒤 리스트에 Dog을 추가했다.
그후 get()메소드가 Dog리턴타입으로 선언했다
ArrayList<Animal> myDogArrayList = new ArrayList<Animal>();
Dog aDog = new Dog();
myDogArrayList.add(aDog);
Dog d=myDogArrayList.get(0) // 이렇게 쓰면 안된다
위에서 Dog이 ArrayList에 들어가면 Animal 타입이 되기때문에 d를 myDogArrayList에 넣으려면 myDogArrayList 다운캐스팅 해야한다.
'인공지능 교육 > Java' 카테고리의 다른 글
21/05/05 8일차 인공지능 교육 (0) | 2021.05.08 |
---|---|
21/05/04 7일차 인공지능 교육 (0) | 2021.05.06 |
21/05/03 5일차 인공지능 교육 (0) | 2021.05.03 |
21/04/30 4일차 인공지능 교육 (0) | 2021.04.30 |