(2020.12.09)

 

상속과 다형성

 

 

객체 지향 프로그래밍의 중요한 특성 중 하나가 상속(Inheritance)이다. 상속은 단어 그대로 물려받다의 의미이다. 즉 B클래스가 A클래스를 상속받으면 B클래스는 A클래스의 멤버 변수나 메서드를 사용할 수 있다.

 

 

inheritance

상속의 표현

 

- A클래스가 B클래스에게 상속한다.

 

- B클래스가 A클래스를 상속받는다.

 

* 상속하는 쪽이 상위 클래스이며, 받는 쪽이 하위 클래스이다.

* 상속을 표현할 때는 받는 쪽에서 하는 쪽으로 화살표가 향한다.

 

 

▶ 클래스 상속 문법

 

Class B extends A{ 
  
  //B클래스가 A클래스를 상속받는다.
   
}

 

자바 문법으로 상속을 구현할 때는 extends 예약어를 사용한다. "class B extends A"는 "B클래스가 A클래스를 상속받는다"라는 의미이며, 상속받는 B가 하위 클래스, 상속하는 A클래스가 상위 클래스이다.

 

상위 클래스는 하위 클래스보다 일반적인 의미를 가지며, 하위 클래스는 상위 클래스보다 구체적인 의미를 가진다. 아래 포유류와 사람을 예로 들었다.

 

 

pic3

 

class Customer{
    private int customerID;
    private String customerName;
    private int bonusRatio;
    
    ...
}

class VIPCustomer extends Customer{
    private int agentID;
    
    ...
}

 

 

접근 제한자

 

  외부 클래스 하위 클래스 동일 패키지 내부 클래스
public O O O O
protected X O O O
(default) X X O O
private X X X O

 

 

super 예약어

super 예약어는 상속 관계일때 하위 클래스에서 상위 클래스로 접근할 때 사용한다. 이전 this 예약어가 자기 자신을 참조할 때와 같은 맥락이다. 상위 클래스에서도 super 예약어를 사용하기도 한다.(object)

 

 

메서드 오버라이딩(Overriding)

 

상위 클래스에 정의된 메서드가 하위 클래스와 기능이 맞지 않거나 추가 기능이 필요한 경우 같은 이름과 매개변수로 하위 클래스에서 재정의 하는 것을 뜻함.

 

쉽게 말해 부모의 메서드를 자식 클래스에서 재정의하는 것이다.

 

public class Customer { 

  public int calcPrice(int price) {
	bonusPoint+= price * bonusRatio;
    return price;
  }
  ...
}

 

Customer 클래스에 제품 가격을 계산하는 calcPrice() 메서드가 있다. 일반 고객인 Customer는 제품의 정가를 지불해야 하지만 VIP 고객은 지정한 할인율이 적용된 가격을 받아야 한다. 

 

public class VIPCustomer extends Customer { 

  @Override
  public int calcPrice(int price) {
	bonusPoint+= price * bonusRatio;
    return price - (int)(price * saleRatio);
  }
  ...
}

 

VIPCustomer는 Customer를 상속받았으므로 calcPrice 메서드의 코드를 조금 수정하여 동일한 메서드의 이름으로 사용할 수 있다. 이것이 메서드 오버라이딩(Overriding)이다.

 

 

 상위 클래스로 묵시적 클래스 형 변환된 경우 오버라이딩된 메서드의 호출은?

 

public class Overriding{

	public static void main(String[] args){
    	
        Customer vip1 = new VIPCustomer();
        vip1.calcPrice(77777);
        
    }
}

 

Customer vip1 = new VIPCustomer(); <- 와 같이 상위 클래스로 형 변환이 된 경우 calcPrice(77777); 메서드는 어느 메서드가 실행될까? 타입인 Customer의 calcPrice() 메서드? 아니면 인스턴스인 VIPCustomer의 calcPrice() 메서드?

 

바로 재정의된 VIPCustomer의 calcPrice() 오버라이딩된 메서드가 호출된다.

 

 

다형성(Polymorphism)

 

다형성은 하나의 코드가 다양한 구현으로 실행되는 것으로 객체지향 프로그래밍의 가장 큰 특징 중 하나로 꼽힌다. 프로그램의 유연성, 재활용성, 유지보수성에 기본이 된다. 

 

다형성은 하나의 클래스를 상속받은 여러 클래스가 있는 경우 각 클래스마다 다른 이름의 서로 다른 메서드를 재정의 한다. 그리고 상위 클래스 타입으로 선언된 하나의 변수가 여러 인스턴스에 대입되어 다양한 구현이 실행될 수 있다.

 

 

Run.class

package polymorphism;

class Animal{
	public void Move() {
		System.out.println("🦠.");
	}
}

class Human extends Animal{
	@Override
	public void Move() {
		System.out.println("🏃~~..️");
	}
}
class Cat extends Animal{
	@Override
	public void Move() {
		System.out.println("🐈~~~...");
	}
}
class Bird extends Animal{
	@Override
	public void Move() {
		System.out.println("🦅~~~~~......");
	}
}

 

상위 클래스인 Animal과 하위 클래스인 Human, Cat, Bird가 존재한다. Move() 메서드는 오버라이딩을 통해 서로 다른 기능을 갖추고 있다.

 

public class Run {
	public static void main(String[] args){
		
		Run run = new Run();
		
		run.MoveAnimal(new Human());
		run.MoveAnimal(new Cat());
		run.MoveAnimal(new Bird());
	}
	
	public void MoveAnimal(Animal animal) {
		animal.Move();
	}
}

 

MoveAnimal(...) 메서드는 Animal을 매개변수로 받아 Move() 함수를 실행한다. MoveAnimal(..) 메서드에 Human과 Cat, Bird를 매개변수로 전달한다. 

 

res

 

간단하게 작성된 코드이기 때문에 다형성을 이해하는데 충분하지 않을 것 같아요. 프로그램의 복잡도나 규모가 커질수록 이해하기 쉬워질듯 합니다.