JAVA/자바 이론 / / 2021. 5. 25. 05:28

Java | 5-2 상속과 다형성

01. 업캐스팅과 instanceof 연산자

02. 메소드 오버라이딩

03. 추상 클래스

04. 인터페이스

 

# 객체의 타입 변환 : 업캐스팅

º 업캐스팅 (upcasting)

- 프로그램에서 이루어지는 자동 타입 변환

- 서브 클래스의 레퍼런스 값을 슈퍼 클래스의 레퍼런스에 대입

→ 슈퍼 클래스의 레퍼런스가 서브 클래스 객체를 가리키게 되는 현상

→ 슈퍼 클래스의 레퍼런스는 서브 클래스 객체 내에 있는 모든 멤버들을 접근할 수 없고, 슈퍼 클래스에서 정의된 멤버들만 접근 가능

 

# 업캐스팅 사례

class Persom {
	String name;
    String id;
    public Person(String name) {
    	this.name = name;
    }
}
class Student extends Person {
	String grade;
    String department;
    public Student(String name) {
    	super(name);
    }
}
public class UpcastingEx {
	public static void main(String[] args) {
    	Person p;
        Student s = new Student("김성철");
        p = s;  // 업캐스팅 발생
        System.out.println(p.name);  // 오류 없음
        p.grade = 'A';  // 컴파일 오류
        p.department = "CSE";  // 컴파일 오류

- 레퍼런스 p를 이용하면 Student 객체의 속성 중에서 오직 Person에서 정의된 속성들만 접근할 수 있다.

 

# 객체의 타입 변환 : 다운캐스팅

º 다운캐스팅(downcasting)

- 슈퍼 클래스 레퍼런스를 서브 클래스 레퍼런스에 대입하는 것

- 업캐스팅 된 것을 다시 원래대로 되돌리는 것

- 다운캐스팅 할 타입을 명시적으로 지정해야 함

 

# 다운캐스팅 사례

public class UpcastingEx {
	public staitc void main(String[] args) {
    	Person p;
        Student s = new Student("김성철");
        
        p = s; // 업캐스팅
        System.out.println(p.name);
        
        Student s2 = (Student) p; // 다운캐스팅
        
        s2.grade = "A";
        s2.department = "CSE";
        System.out.println(s2.name);
    }
}

 

# instanceof 연산자와 객체 구별

º 업캐스팅 된 레퍼런스로 객체의 원래 타입을 구분하기 어려움

- 하나의 슈퍼 클래스는 여러 서브 클래스에 상속될 수 있기 때문 !

º instanceof 연산자

- instanceof를 이용하여 레퍼런스가 가리키는 객체의 원래 타입을 식별함

- 사용법 :

객체 레퍼런스 instanceof 클래스 타입  --> true/false의 불린 값

 

# 메소드 오버라이딩(Method Overriding)

- 슈퍼 클래스의 메소드를 서브 클래스에서 재정의하는 것

→ 슈퍼 클래스의 메소드를 이름, 메소드 인자 타입 및 개수, 리턴 타입 등 모든 것을 동일하게 정의한다.

(이 중에서 하나라도 다르면 메소드 오버라이딩이 실패한 것임)

- 슈퍼 클래스의 "메소드 무시하기"로 번역되기도 함

- 동적 바인딩 발생

→ 오버라이딩 된 메소드가 무조건 실행되도록 동적 바인딩이 된다.

- 슈퍼 클래스의 메소드를 무시하고 서브 클래스에서 새로 작성된 메소드가 실행된다.

 

# 메소드 오버라이딩 만들기

public class DObject {  // 슈퍼 클래스
	public DObject next;
    public DObject() {next = nu11;}
    public void draw() {
    	System.out.println("DObject draw");
    }
}
public class Line extends DObject {
	public void draw() {  // method overriding
    	System.out.println("Line");
    }
}
public class Rect extends DObject {
	public void draw() {  // method overriding
    	System.out.println("Rect");
    }
}
public class Circle extends DObject {
	public void draw() {  // method overriding
    	System.out.println("Circle");
    }
}

 

public class MethodOverridingDemo {
	public static void main(String[] args) {
    	DObject obj = new DObject();
        Line line = new Line();
        DObject p = new Line();  // 업캐스팅
        DObject r = line;
        
        obj.draw();   //DObject.draw()
        line.draw();  //Line.draw()
        p.draw();     //Line.draw()
        r.draw();     //Line.draw()
        
        DObject rect = new Rect();
        DObject circle = new Circle();
        rect.draw();    //Rect.draw()
        circle.draw();  //Circle.draw()
    }
} 

- 실행 시간에 객체 속에 오버라이딩 한 메소드가 있으면 동적 바인딩 되어 그 메소드가 실행됨

 

# 메소드 오버라이딩 조건

(1) 반드시 슈퍼 클래스 메소드와 동일한 이름, 동일한 호출 인자, 반환 타입을 가져야 한다.

(2) 오버라이딩 된 메소드의 접근 지정자는 슈퍼 클래스의 메소드 접근 지정자보다 좁아질 수 없다.

public > protected > default > private 순으로 지정 범위가 좁아진다.

(3) 반환 타입만 달라도 오류

(4) static, private 또는 final 메소드는 오버라이딩 될 수 없다.

 

# super 키워드

- super는 서브 클래스에서 슈퍼 클래스의 멤버를 접근할 떄 사용되는 슈퍼 클래스 타입의 레퍼런스

- 상속 관계에 있는 서브 클래스에서만 사용됨

- 오버라이딩 된 슈퍼 클래스의 메소드 호출 시 사용

- 필드와 메소드 접근 모두 가능

 

# this vs super, this() vs super() 사용

º this 레퍼런스 vs super 레퍼런스

레퍼런스 this super
사용 현재 객체의 모든 멤버에 접근 - 현재 객체 내에 있는 슈퍼 클래스
멤버를 접근
- super로 메소드 호출 시 정적바인딩 실행
사용법 this.객체 내의 멤버 super.객체 내의 슈퍼클래스의 멤버

º this() vs super()

메소드 this() super()
사용 생성자에서 다른 생성자를 호출할 때
사용
서브 클래스의 생성자에서 슈퍼 클래스의 생성자를 호출할 떄 사용

 

# 오버라이딩 vs 오버로딩

비교 요소 메소드 오버로딩 메소드 오버라이딩
정의 같은 클래스나 상속 관계에서 동일한
이름의 메소드 중복 작성
서브 클래스에서 슈퍼 클래스에 있는
메소드와 동일한 이름의 메소드 재작성
관계 동일한 클래스 내 혹은 상속 관계 상속 관계
목적 이름이 같은 여러 개의 메소드를 중복 정의하여 사용의 편리성 향상 슈퍼 클래스에 구현된 메소드를
무시하고 서브 클래스에서 새로운
기능의 메소드를 재정의하고자 함
조건 메소드 이름은 반드시 동일함. 메소드의 인자의 개수나 인자의 타입이 달라야
성립
메소드의 이름, 인자의 타입,
인자의 개수, 인자의 리턴 타입 등이
모두 동일하여야 성립
바인딩 정적 바인딩. 컴파일 시에 중복된
메소드 중 호출되는 메소드 결정
동적 바인딩. 실행 시간에 오버라이딩 된 메소드 찾아 호출

 

# 추상 메소드와 추상 클래스

º 추상 메소드 (abstract method)

- 선언되어 있으나 구현되어 있지 않은 메소드

- 정의 : 접근 지정자 abstract 반환형 메소드 이름();

→ 추상 메소드는 서브 클래스에서 오버라이딩하여 구현한다.

º 추상 클래스 (abstract class)

- 추상 메소드를 하나라도 가지고 있으면 추상 클래스이다.

→ 클래스 앞에 반드시 abstract 라고 선언해야 한다.

- 추상 메소드를 가지고 있지는 않지만 클래스 앞에 abstract 로 선언한 경우

 

# 추상 클래스의 특성

º 추상 클래스의 객체는 생성할 수 없다.

º 추상 클래스의 필요성

- 계층적 상속 관계를 갖는 클래스 구조를 만들 때

- 설계와 구현 분리

→ 슈퍼 클래스에서는 개념적 특징을 정의하고, 서브 클래스에서 구체적 행위를 구현한다.

º 추상 클래스의 상속

- 추상 클래스를 상속받은 서브 클래스가 추상 메소드를 또 구현하지 않으면 서브 클래스도 추상 클래스가 된다.

→ abstract로 정의하여야 한다.

- 서브 클래스에서 추상 메소드를 구현하면 서브 클래스는 추상 클래스가 되지 않는다.

 

# 자바의 인터페이스 (interface)

º 인터페이스

- 모든 메소드가 추상 메소드인 "클래스"

- 인터페이스는 상수와 메소드만 갖는다.

º 인터페이스 정의

- interface 키워드로 정의된 클래스

ex) public interface SerialDriver { ... }

º 인터페이스의 특징

- 모든 메소드 : public abstract (생략 가능)

- 모든 상수 : public static final (생략 가능)

- 객체를 생성할 수 없음 → 생성자를 가질 수 없음.

- 레퍼런스 변수 타입으로 사용 가능

 

# 자바 인터페이스의 특징

º 멤버는 추상 메소드와 상수만으로 구성

- 필드는 가지지 않음

- 메소드는 모두 추상메소드이며, 메소드 선언 시 abstract 키워드 생략 가능

º 모든 메소드는 public 접근 지정자이며 생략 가능

º 상수도 public static final을 생략하여 선언 가능

- int ONEDAY = 24;

º 인터페이스의 객체를 생성할 수 없음(추상 메소드만 가질 수 있음)

º 다른 인터페이스에 상속될 수 있음

- 인터페이스는 다른 인터페이스를 상속할 수 있음

º 인터페이스도 레퍼런스 변수의 타입으로 사용가능

- Clock clock;  // 인터페이스 Clock의 레퍼런스 변수 clock

- Car car;  // 인터페이스 Car의 레퍼런스 변수 car

 

# 인터페이스의 필요성

º 인터페이스를 이용하여 다중 상속 구현

- 클래스는 다중 상속 불가

º 인터페이스는 명세서와 같음

- 구현은 블랙 박스와 같아 인터페이스의 사용자는 구현에 대해 알 필요 없음

º 인터페이스만 정의하고 구현을 분리하여, 작업자가 다양한 구현을 할 수 있음

 

# 인터페이스 상속

- 인터페이스 간에도 상속이 가능하다.

→ 인터페이스를 상속하여 확장된 인터페이스를 작성할 수 있다.

- 다중 상속을 허용한다.

 

# 인터페이스 구현

- implements 키워드를 사용한다.

- 여러 개의 인터페이스를 동시에 구현할 수 있다.

- 상속과 구현이 동시에 가능하다.

 

# 추상 클래스와 인터페이스 비교

º 추상 클래스

- 일반 메소드도 포함 가능

- 상수, 변수 필드 포함 가능

- 모든 서브 클래스에 공통된 메소드가 있는 경우, 추상 클래스가 적합

º 인터페이스

- 모든 메소드가 추상 메소드

- 상수 필드만 포함 가능

- 다중 상속 지원

 

# 요약

  • 자바에서 상속은 부모 클래스의 필드와 메소드를 자식 클래스에게 물려주는 것으로 부모 클래스를 슈퍼 클래스, 자식 클래스를 서브 클래스라고 함.
  • 자바는 클래스의 다중 상속을 지원하지 않음
  • 자바에서 상속의 선언은 extends 키워드를 사용함
  • 서브 클래스의 객체에는 슈퍼 클래스의 필드와 메소드가 포함되어 있으나 슈퍼 클래스의 private 멤버는 서브 클래스에서 접근할 수 없음. 슈퍼 클래스의 protected 멤버는 패키지 소속과 상관없이 서브 클래스에서 접근이 가능하며 동일한 패키지 내의 클래스에서도 접근이 가능
  • 서브 클래스의 인스턴스가 생성되면 항상 서브 클래스의 생성자 한 개와 슈퍼 클래스의 생성자 한 개가 실행됨
  • 서브 클래스 객체는 슈퍼 클래스 타입으로 자동 타입 변환이 가능하며 이를 업캐스팅(upcasting)이라고 하며, 다시 원래의 타입으로 강제 타입 변환하는 것을 다운캐스팅(downcasting)이라고 함.
  • instanceof 연산자는 결과 값이 boolean 타입이며 객체가 어떤 클래스 타입인지 판별할 수 있음
  • 슈퍼 클래스에 정의된 메소드를 서브 클래스에서 재정의하는 것을 메소드 오버라이딩(overriding)이라고 함
  • 서브 클래스에서 슈퍼 클래스의 메소드를 오버라이딩하게 되면 서브 클래스의 인스턴스는 동일한 이름의 메소드를 두 개 가지게 됨. 이 때 오버라이딩된 서브 클래스의 메소드가 항상 실행됨.
  • 호출된 메소드를 실행 시간에 찾아서 실행하는 것을 동적 바인딩이라고 부르며 오버라이딩 된 메소드는 동적 바인딩 방식으로 호출되고 실행됨.
  • 추상 메소드(abstract method)는 메소드의 프로토타입만 있고 실행 코드를 작성하지 않은 미완성의 메소드임. 추상 메소드를 정의하려면 메소드 이름 앞에 abstract라고 선언하여야 함.
  • 추상 클래스(abstract class)는 abstract 키워드로 선언된 클래스이며 한 개 이상의 추상 메소드(abstract)를 포함하는 경우 반드시 추상 클래스로 선언하여야 함.
  • 추상 메소드를 하나도 가지고 있지 않은 경우라도 추상 클래스로 선언하는 것이 가능
  • 추상 클래스의 객체 혹은 인스턴스는 생성될 수 없음
  • 인터페이스(Interface)는 일종의 추상 클래스로서 변수 멤버를 가지지 못함
  • 인터페이스를 정의하기 위해 interface라는 키워드를 사용함
  • 클래스가 인터페이스를 구현할 때 implements 키워드를 사용함. 그리고 인터페이스에 정의된 모든 메소드를 구현하여야 함.

'JAVA > 자바 이론' 카테고리의 다른 글

Java | 7-1 제네릭과 컬렉션  (0) 2021.06.10
Java | 6 패키지  (0) 2021.06.06
Java | 5-1 상속과 다형성  (0) 2021.05.25
Java | 4-3 클래스와 객체  (0) 2021.04.15
Java | 4-2 클래스와 객체  (0) 2021.04.14
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유