다형성

2023. 6. 15. 16:36Java/객체지향

1. 다형성이란? (Polymorphism)

- 다형성이란 여러가지 형태를 가질수 있는 능력을 의미한다

- 자바에서는 한 타입의 참조변수로서 여러 타입의 객체를 참조할 수 있도록 함으로써 다형성을 구현하였다.

즉, 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있도록 하였다는 것이다.

- 예시로 설명

1) CaptionTv라는 클래스가 Tv라는 클래스를 상속받아 기능을 확장

Tv t = new Tv();

CaptionTv c = new CaptionTv();

2) 원래는 인스턴스의 타입과 참조변수의 타입이 일치하는 것이 보통이지만, Tv과 CaptionTv와 같이 클래스가 서로 상속관계에 있을 경우,

조상 클래스 타입의 참조변수(Tv)로 자손 클래스 인스턴스(CaptionTv)를 참조하도록 하는 것이 가능.

Tv t = new CaptionTv();

3) 인스턴스를 같은 타입의 참조변수로 참조하는 것과 조상타입의 참조변수로 참조하는 것의 차이

CaptionTv c = new CaptionTv();

Tv t = new CaptionTv();

참조변수 c와 t는 모두 CaptionTv 인스턴스를 참조하도록 하였지만

참조변수 t로는 CaptionTv의 인스턴스 중에서 Tv클래스의 멤버들만! 사용할 수 있다.

둘 다 같은 타입의 인스턴스이지만 참조변수의 타입에 따라 접근할 수 있는 멤버의 개수가 달라지는 것.

4) 자속타입의 참조변수로 조상타입의 인스턴스를 참조하는 것은 불가능하다.

CaptionTv c = new Tv(); -> Error!

실제 인스턴스인 Tv의 멤버 개수보다 참조변수 c가 사용할 수 있는 멤버 개수가 많아지면

c는 이상한 곳을 가리키게 되기 때문에 에러가 일어난다.

그러므로 참조변수가 사용할 수 있는 멤버의 개수는 인스턴스의 멤버 개수와 같거나 그 보다 적어야한다.

5) 정리

조상타입의 참조변수로 자손타입의 인스턴스 참조 가능

Tv t = new CaptionTv(); -> OK

반대로 자손타입의 탐조변수로 조상타입의 인스턴스 참조는 불가능

CaptionTv c = new Tv(); -> Error!

2. 참조변수의 형변환

- 기본형 변수와 같이 참조변수도 형변환이 가능하나 서로 상속관계에 있는 클래스 사이에서만 가능하다.

- Up-casting : 자손타입 -> 조상타입 (형변환 생략 가능)

- Down-casting : 조상타입 -> 자손타입 (형변환 생략 불가)

- 자손에서 조상으로는 다룰 수 있는 멤버를 잘라내는 거니까 문제 없지만,

조상에서 자손으로는 다룰 수 있는 멤버를 늘리는 거니까 문제가 발생할 수 있다. 그래서 형변환 생략이 불가한 것.

- 형변환은 참조변수의 타입을 변환하는 것이지 인스턴스를 변환하는 것은 아니기 때문에 참조변수의 형변화은 원래 인스턴스에 아무런 영향을 미치지 않는다. 단지 이를 통해 참조하고 있는 인스턴스에서 사용할 수 있는 멤버의 범위(개수)를 조정하는 것뿐이다.

- 서로 상속관계에 있는 타입의 참조변수 간의 형변환은 양방향으로 자유롭게 수행될 수 있으나, 위에서 말했다시피 참조변수가 가리키는 인스턴스의 자손타입으로 형변환은 허용되지 않는다.

3. instanceof 연산자

- 참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위한 연산자

- (참조변수) instanceof (타입명) -> 연산결과로 true, false값

-실제 인스턴스와 같은 타입뿐만 아니라 조상타입의 연산에도 true값을 결과로 얻는다.

c instanceof CaptionTv; //true

c instanceof Tv; //true

c instanceof Object; //true

4. 참조변수와 인스턴스의 연결

멤버변수가 조상 클래스와 자손 클래스에 중복으로 정의된 경우

1) 조상타입의 참조변수를 사용했을 때는 조상 클래스에 선언된 멤버변수가 우선으로 사용되고

2) 자손타입의 참조변수를 사용했을 때는 자손 클래스에 선언된 멤버변수가 사용된다.

5. 매개변수의 다형성

void buy (Product p) {money -= p.price;} //Buyer클래스의 멤버메서드

-> 매개변수가 Product타입의 참조변수라는 것은,

메서드의 매개변수로 Product클래스의 자손타입의 참조변수면(Computer, Tv, Audio) 어느 것이나

매개변수로 받아들일 수 있다는 것이다.

6. 여러 종류의 객체를 배열로 다루기

- 조상타입의 참조변수로 자손타입의 객체를 참조하는 것이 가능하므로

조상타입의 참조변수 배열을 사용하면, 공통의 조상을 가진 서로 다른 종류의 객체를 배열로 묶어서 다룰 수 있다.

- 객체들을 하나의 배열로 다룰때 포인트는

배열은 객체를 가리키는 "참조변수의 배열"이므로 반드시 참조변수에 해당 인스턴스를 생성(new)해야한다는 것