[Java] 상속(2)

업캐스팅과 instanceof 연산자

캐스팅 : 타입 변환

업캐스팅

: 서브 클래스 → 슈퍼 클래스

: 서브 클래스의 객체에 대한 레퍼런스를 슈퍼 클래스의 타입으로 변환하는 것.

: 슈퍼 클래스의 레퍼런스로 서브 클래스의 객체를 가리키게 한다.

▶서브 클래스는 슈퍼 클래스의 속성을 상속받아 서브 클래스의 객체는 슈퍼 클래스의 멤버를 모두 가진다.

  ∴ 서브 클래스의 객체를 슈퍼 클래스의 객체로 취급 가능.

class Person{
    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);	//기본 생성자가 아닌 사용자가 명시적으로 슈퍼클래스의 생성자 선택(Person(String 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 = "software";	// 컴파일 오류 발생
    }
}

슈퍼 클래스 타입의 레퍼런스 p가 서브 클래스 객체(s)를 가리키도록 치환됨. → 업캐스팅

※ 레퍼런스 p는 Person 클래스의 멤버만 접근 가능. → p는 Person 타입이기 때문

※ 업캐스팅한 레퍼런스는 슈퍼 클래스의 멤버만 접근 가능.

▶ 서브 클래스 객체가 슈퍼 클래스 타입으로 업캐스팅되면, 슈퍼 클래스 타입의 객체로 취급되며 서브 클래스의 필드나 메소드는 접근 불가.

 

다운캐스팅

: 슈퍼 클래스 → 서브 클래스

: 슈퍼 클래스 타입의 레퍼런스를 서브 클래스 타입의 레퍼런스로 변환하는 것.

Person p = new Student("가나다");	//업캐스팅
Student s = (Student)p;		//다운캐스팅

System.out.println(s.name);
s.garade = "A";

※ 타입 변환을 반드시 표시

s를 통해 Student 객체 전체를 접근 가능.

 

업캐스팅과 instanceof 연산자

업캐스팅을 여러 개 한 경우 어떤 클래스의 객체가 전달되었는지 알 수 없다.

 

▶instanceof 연산자 사용

레퍼런스가 가리키는 객체가 어떤 클래스 타입인지 구분.

레퍼런스 instanceof 클래스명

instanceof 연산자의 결과 값은 boolean.

레퍼런스가 가리키는 객체가 해당 클래스 타입의 객체 : true

                                                             아니면 : false

 

 

메소드 오버라이딩

슈퍼 클래스에 선언된 메소드와 같은 이름, 리턴 타입, 매개 변수를 갖는 메소드를 서브 클래스에서 재작성하는 것.

= 슈퍼 클래스 메소드 무시하기 or 덮어쓰기

class Shape{
	public void draw(){
    	System.out.println("Shape");
    }
}

class Line extends Shape{
	public void draw(){
		System.out.println("Line");
    }
}
Line line = new Line();
line.draw();

서브 클래스 레퍼런스로 오버라이딩된 메소드 호출

 

new Line()으로 생성된 객체에는 2개의 draw() 메소드가 존재.

레퍼런스 line이 Line 타입 이므로 컴파일러는 line.draw() 호출.

 

동적 바인딩

슈퍼 클래스의 메소드를 무시하고 서브 클래스에서 오버라이딩된 메소드가 무조건 실행 되는 것.

Shape shape = new Line();	// 업캐스팅
shape.draw();

업캐스팅에 의해 슈퍼 클래스 레퍼런스로 오버라이딩된 메소드 호출(동적 바인딩)

 

shape이 Shape 타입이므로 Shape 클래스에 draw() 멤버가 있는지 확인 후 호출.

but, Shape의 draw()를 오버라이딩 한 Line의 draw()가 존재해 Line()의 draw()가 실행.

 

@Override

오버라이딩이 정확한지 컴파일러에게 확인하도록 지시

 

메소드를 오버라이딩할 때 조건

1. 슈퍼 클래스의 메소드와 동일한 원형으로 작성.

   : 슈퍼 클래스의 메소드와 동일한 이름, 매개변수 타입과 개수, 리턴 타입을 갖는 메소드를 작성.

 

2. 슈퍼 클래스 메소드의 접근 지정자보다 접근 범위를 좁혀 오버라이딩 불가.

   : public > protected > 디폴트 > private 순으로 접근 범위가 좁아진다.

   : ex) protected로 선언된 메소드는 protected or public으로만 오버라이딩 가능.

 

3. static, private, final로 선언된 메소드는 서브 클래스에서 오버라이딩 불가.

 

오버라이딩과 super 키워드

서브 클래스에서 super 키워드를 사용하여 정적 바인딩을 통해 슈퍼 클래스의 멤버에 접근 가능.

 

super

슈퍼 클래스에 대한 레퍼런스. 슈퍼 클래스의 필드와 메소드 모두 접근 가능.

super.슈퍼클래스 멤버 or 슈퍼 클래스 메소드
더보기

▶ this, this(), super, super() 차이 ◀

 

this : 레퍼런스로서 현재 객체의 모든 멤버 접근

super : 레퍼런스로 현재 객체 내에 있는 슈퍼 클래스 멤버 접근. super로 메소드 호출 시 정적 바인딩 실행.

this() : 메소드 호출. 생성자에서 다른 생성자를 호출할 때 사용.

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

 

오버로딩과 오버라이딩

오버로딩

메소드 이름으 같지만, 매개변수 타입이나 개수가 다르게 메소드를 작성.

( 동일한 클래스 내, 상속 관계 둘 다 성립 )

 

오버라이딩

슈퍼 클래스의 메소드 이름, 타입, 개수 등 모두 동일하게 서브 클래스에서 재작성.

( 상속 관계에서만 성립 )

  메소드 오버로딩 메소드 오버라이딩
조건 메소드 이름은 반드시 동일.
매개변수 타입이나 개수 달라야 성립.
메소드 이름, 매개변수 타입, 개수, 리턴 타입 모두 동일해야 성립.
관계 동일한 클래스 내 혹은 상속 관계 상속 관계
목적 이름이 같은 여러 개의 메소드를 중복 작성하여 사용의 편리성 향상.
다형성 실현
슈퍼 클래스에 구현된 메소드를 무시하고 서브 클래스에서 새로운 기능의 메소드를 재정의하기 위해.
다형성 실현
바인딩 정적 바인딩. 동적 바인딩
선언 같은 클래스나 상속 관계에서 동일한 이름의 메소드 중복 작성 서브 클래스에서 슈퍼 클래스에 있는 메소드와 동일한 이름의 메소드 재작성

 

추상 클래스

추상 메소드

선언은 되어있지만 코드는 구현되어 있지 않은 메소드

abstract 키워드로 원형만 선언하고 코드는 구현하지 않는다.

public abstract String set();

 

추상 클래스

abstract 키워드로 선언해야 한다.

1. 추상 메소드 포함하는 클래스

abstract class Shape{
	...
    abstract public void draw();
}

※ 추상 메소드를 가지고 있으면 반드시 추상 클래스로 선언.

 

2. 추상 메소드는 없지만 abstract로 선언한 클래스

abstract class Shape{
	...
}
더보기

※ 추상 클래스는 객체를 생성할 수 없다. ※

추상 클래스에는 실행 코드가 없는 추상 메소드가 있을 수 있어 추상 클래스의 객체를 생성하면 컴파일 오류 발생.

but, 레퍼런스 변수를 선언하는 것은 오류가 발생하지 않는다.

 

추상 클래스 상속

추상 클래스를 상속받는 서브 클래스도 추상 클래스가 된다. 

∴ 서브 클래스에도 abstract를 붙여 추상 클래스임을 명시해야 한다.

 

추상 클래스 구현

슈퍼 클래스에 선언된 모든 추상 메소드를 서브 클래스에서 오버라이딩하여 실행 가능한 코드로 구현하는 것.

 

 

더보기

추상 클래스를 이용하면 응용 프로그램의 설계와 구현의 분리가 가능하다.

추상 클래스로 기본 방향을 잡고 서브 클래스에서 구현하면 구현 작업이 쉬워진다.

추상 클래스는 계층적 상속 관계를 가지는 클래스들의 구조를 만들 때 적합하다.

 

인터페이스

서로 다른 하드웨어 장치들이 상호 데이터를 주고받을 수 있는 규격.

interface 키워드를 사용하여 선언.

 

상수와 추상 메소드

: public abstract, 생략 가능, 다른 접근 지정으로 지정될 수 없다.

 

default 메소드

: public으로 접근 지정 고정. 인터페이스 내 코드 작성 필수.

 

private 메소드

: 인터페이스 내에서만 호출 가능. 인터페이스 내 코드 작성 필수.

 

static 메소드

: 접근 지정이 생략되면 public, private으로 지정 가능. 인터페이스 내 코드 작성 필수.

 

  • 인터페이스는 객체를 생성할 수 없다.
  • 인터페이스 타입의 레퍼런스 변수는 선언 가능하다.
  • 인터페이스끼리 상속된다.
  • 인터페이스를 상속받아 클래스를 작성하면 인터페이스의 모든 추상 메소드를 구현하여야 한다.

인터페이스 구현

implements 키워드를 사용하여 인터페이스의 모든 추상 메소드를 구현한 클래스를 작성하는 것.

 

 

 

 

반응형

'Back-End > Java' 카테고리의 다른 글

[Java] for-each문 사용법  (0) 2023.01.04
[Java] 주요 패키지 내 클래스  (0) 2022.03.17
[Java] 상속(1)  (1) 2022.02.21
[Java] static 멤버와 final  (1) 2022.02.18
[Java] 접근 지정자  (0) 2022.02.18