JAVA 05 : 다형성, 상속, 오버라이딩

LeeWonjin·2022년 7월 18일

2022 백엔드스터디

목록 보기
5/20

Do it! 자바 프로그래밍 입문 8장

다형성

  • 같은 내용의 코드라도 다양한 내용을 나타낼 수 있는 성질 (여러 자료형으로 구현되고 실행되는 것)
  • 오버로딩, 오버라이딩(상속) 등으로 구현

다형성(Polymorphism)이란

상속

  • 이미 구현된 클래스를 상속한 뒤 확장하는 방식으로 새로운 클래스를 구현할 수 있음
  • 코드를 재사용하는 방법 중 하나 (코드를 재사용하기 위한 목적으로 상속을 하는 것은 아님)
  • if분기의 대안이 될 수 있음
class 클래스식별자 extends 부모클래스_식별자 {
  클래스 구현
}

용어

  • 상속 해주는 클래스 : 상위, parent, base, super 클래스
  • 상속 받는 클래스 : 하위, child, derived, sub 클래스

부모는 자식보다 일반적이다. (자식은 부모보다 구체적이다)

상속으로 형성된 부모-자식은 IS-A관계를 갖는다.
이는 HAS-A관계를 갖는 합성과는 다르다.

Incheol's TECH BLOG : 상속보단 합성

// Test.java
package classclass;

public class Test {
	public static void main(String[] args) {
		Child a = new Child(123, "Lee", 53);
		System.out.println(a.getId()); // 123
		a.setName("Kim");
		System.out.println(a.getName()); // Kim
		
		a.printInfo(); // ID : 123, Name : Kim, Age : 53
	}
}

// Parent.java
package classclass;
public class Parent {
	// field
	protected int id;
	protected String name;
	
	// constructor
	public Parent(int id, String name) {
		this.id = id;
		this.name = name;
	}
	
	// getter, setter
	public int getId() {
		return id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

// Child.java
package classclass;
public class Child extends Parent {
	// field
	protected int age;
	
	// constructor
	public Child(int id, String name, int age) {
		super(id,  name);
		this.age = age;
	}
	
	// method
	public void printInfo() {
		System.out.println("ID : "+id+", Name : "+name+", Age : "+age);
	}
	
	// getter setter
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

메모리 상태

자식 인스턴스를 어딘가에서 생성하면 아래와 같은 과정을 거친다.
1. 먼저 자식 클래스의 생성자 호출되어 진입
2. 부모 생성자 super(...)가 호출
3. 부모 인스턴스 생성
4. 자식 생성자에서 나머지 내용 실행
5. 자식 인스턴스 생성

즉, 자식을 인스턴스화 하면 부모도 인스턴스화 된다.
자식에서 접근할 수 없는 private필드라도 접근만 할 수 없을 뿐, 메모리상에는 모두 적재된다.

업캐스팅

자식을 부모 타입으로 묵시적으로 캐스팅하는 것
이것이 가능한 이유는 자식 인스턴스를 생성하면서 부모 또한 생성되었기 때문

package classclass;
public class Test {
	public static void main(String[] args) {
		Child a = new Child(123, "Lee", 53);
		
		Parent b = a; // up-casting
		System.out.println(b.getName()); // Lee
		b.setName("new name");
		System.out.println(b.getName()); // new name
		
		/*
		b.printInfo(); // compile error
        // 에러나는 이유 : Parent에는 printInfo()가 없다.
		*/
        
        Child c = (Child)b; // down-casing
		c.printInfo(); // ID : 123, Name : new name, Age : 53
	}
}

다운캐스팅

부모를 자식으로 캐스팅하려면 명시적으로 캐스팅해야 함
위 코드의 Child c = (Child)b; 문장이 예시

instanceof

instanceof키워드로 인스턴스 타입 확인가능
어떤 인스턴스가 특정 클래스로 다운캐스팅이 가능한지 여부를 확인할 때 유용

package classclass;
public class Test {
	public static void main(String[] args) {
		Child c1 = new Child(1, "WONJIN", 12);
		Parent c2 = new Child(333, "KIM", 66666);
		Parent c3 = new Parent(100, "IamParent");
		
		// instanceof
		System.out.println("<intsance> instanceof Child");
		System.out.println(c1 instanceof Child); // true
		System.out.println(c2 instanceof Child); // true
		System.out.println(c3 instanceof Child); // false
		System.out.println();
	}
}

오버라이딩

가상메소드 (virtual method)

타입에 관계없이 실제 생성된 인스턴스의 메소드가 호출되는 원리

오버라이드 예시

아래 코드는 Parent의 printMe()를 Child가 상속받아 오버라이드하는 모습을 보임

c2 참조변수는 Parent타입이지만, 그 인스턴스는 Child임.
가상메소드 원리에 따라 Child에서 재정의된 printMe()를 호출하는 것을 확인할 수 있음

// Test.java ( 프로그램 진입점 )
package classclass;
public class Test {
	public static void main(String[] args) {
		Child c1 = new Child(1, "WONJIN", 12);
		Parent c2 = new Child(333, "KIM", 66666);
		
		// [Child] id : 1 / name : WONJIN / age : 12
		c1.printMe();
	
		// [Child] id : 333 / name : KIM / age : 66666
		c2.printMe();
	}
}

// Parent.java
package classclass;
public class Parent {
	protected int id;
	protected String name;
	
	public Parent(int id, String name) {
		this.id = id;
		this.name = name;
	}
	public void printMe() {
		System.out.println("[Parent] id : " + id + " / name : " + name);
	}
}

// Child.java
package classclass;
public class Child extends Parent {
	protected int age;
	
	public Child(int id, String name, int age) {
		super(id,  name);
		this.age = age;
	}
    
    @Override
	public void printMe() {
		System.out.println("[Child] id : " + id + " / name : " + name + " / age : " + age);
	}
}

자바 어노테이션

자바 어노테이션

@Override는 오버라이드 할 것임을 컴파일러에게 명시적으로 전달하기 위한 주석

  • @Override가 없어도 정상적으로 오버라이드 및 컴파일 됨
  • 의의 : 이 어노테이션을 붙이고 오버라이드 되지 않는 메소드를 작성한 경우 컴파일에러 표시

The method <메소드 이름> of type <@Override 어노테이션이 있는 클래스> must override or implement a supertype method

profile
노는게 제일 좋습니다.

0개의 댓글