다형성 (Polymorphism)
특징
- 부모 클래스 타입으로 자식 클래스 타입의 객체를 참조하는 특징
- 부모 클래스 타입으로 자식 클래스의 메소드는 사용할 수 없다.
1 2 3 4
Bar bar = new Bar(); // 자식 객체 생성. Foo foo = (Foo)bar; // 부모 클래스 타입으로 형변환하여 자식 객체를 받음. foo.methodA(); // 사용 가능 foo.methodB(); // 사용 불가능. 자식 클래스의 메소드는 문법적으로 사용할 수 없다.
- 자식 클래스 타입으로 부모 클래스를 형변환 할 수 없다.
1 2
Foo foo1 = new Foo(); Bar bar1 = (Bar) foo1; // 문법 오류는 아니지만 자식클래스 타입으로 형변환하여 부모객체를 받는것 자체로 런타임에러가 발생한다.
- 오버라이딩에 의한 다형성 ```java class Foo1{ public String x = “Super”;
1 2 3 4 5 6 7 8
System.out.println("Super Method"); } } class Bar1 extends Foo1{ public String x = "Sub"; @Override public void MethodA(){ System.out.println("Sub"); } } ``` + 멤버 변수를 재정의 하는 경우 선언된 객체의 타입을 따른다. ```java Bar1 bar1 = new Bar1(); Foo1 foo1 = (Foo1) bar1; System.out.println(bar1.x); // Sub System.out.println(foo1.x); // Super //foo1은 문법적으로 Foo1의 객체이므로 foo1.x는 Foo1클래스의 x가 호출된다. ``` + 메소드 오버라이딩은 메모리상의 객체 타입을 따른다. ```java Bar1 bar1 = new Bar1(); Foo1 foo1 = (Foo1) bar1; bar1.MethodA(); // Sub foo1.MethodA(); // Sub //foo1은 bar1의 메모리를 참조하고 있으므로 Bar1의 MethodA가 호출된다. ``` + 위의 경우에 Foo1의 MethodA는 호출 될 일이 없다. 하지만 이를 선언하지 않으면 문법상 문제가 생긴다. 이처럼 문법을 맞추기 위해 구현되어있는 메소드를 가상 메소드 호출(Virtual method call)이라 부른다.
- 부모 클래스 타입으로 자식 클래스의 메소드는 사용할 수 없다.
- 공변 반환 타입
1 2 3 4 5 6 7 8 9 10 11
class Foo3{ public Foo3 getInstance(){ return this; } } class Bar3 extends Foo3{ @Override public Bar3 getInstance(){ // 오버라이드의 경우 항상 리턴타입이 동일해야 하지만, 객체 자신을 반환하는 경우에는 다를 수 있다. return this; } }
- 객체 지향의 특성상 위와 같은것이 옳지 않지만 코드의 편의성을 위해 예외적으로 가능하게 되었다.
- 꼭 return type이 객체 자신이 아니더라도 상속의 상하관계만 잘 맞는다면 어떤 것이 들어와도 사용 가능하다. (Object - Bar3) or (Foo3 - Bar3)
추상 클래스 (Abstract Class)
특징
- 일부 메소드가 구현되지 않고, 선언만 되어있는 클래스이다.
- 자식 클래스에서 이것을 반드시 구현하게끔 강제하는 것이다.
- 필요한 모든 클래스가 구현될 수 있도록 하여 안정성을 높인다.
- 구성 메소드를 각각 다르게 만들수 있기 때문에 추상 클래스를 활용해 다양한 종류의 클래스 생성이 가능하다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
abstract class AbstractFoo{ int x, y; public void method(){ System.out.println("method"); } public abstract void absractMethod(); // 선언만 하고 구현하지 않음 // Virtual method call과 같다. } class Foo extends AbstractFoo{ @Override public void absractMethod() { System.out.println("Implemented abstractMethod"); } }
- 추상 클래스는 객체 생성이 불가능하다. 하지만 구현된 자식 클래스의 객체는 받을 수 있다.
1 2 3
//AbstractFoo afoo = new AbstractFoo(); // 추상 클래스는 객체 생성이 불가능하다. AbstractFoo afoo = (AbstractFoo) foo; afoo.absractMethod(); // 실행 가능