본문 바로가기
Java

상속

by 청원뿔세포 2022. 10. 19.

상속이란

부모가 자식에게 물려주는 행위를 말한다.

부모 클래스를 상위 클래스라고 부르기도 하고, 자식 클래스를 하위 클래스, 또는 파생 클래스라고 부른다.

이미 잘 개발된 클래스를 재사용해서 새로운 클래스를 만들기 때문에 코드이 중복을 줄여준다.

 

자식 객체를 생성하면 부모객체가 먼저 생성되고, 자식 객체가 그 다음에 생성된다.

 

메소드 재정의 override

자식 클래스에서 부모의 메소드를 사용하지 않고 수정하여 사용할 때 메소드 재정의를 하게된다.

메소드 재정의를 하게 되면 메소드 호출 시 자식의 메소드가 호출된다.

 

메소드 재정의 시 주의할 점

- 부모의 메소드와 동일한 시그니처

- 접근제한을 더 강하게 오버라이딩할 수 없다.

- 새로운 예외를 throws할 수 없다.

 

만약 부모 메소드를 호출하고 싶다면 super키워드를 통해 호출할 수 있다.

class 자식 extends 부모 {
	method2 () { // 오버라이딩
	}
	.
	.
	.
	method2 (); // 오버라이딩된 메소드 호출
	super.method2 (); //부모 메소드 호출

 

final 클래스와 final 메소드

final 키워드를 통해 클래스, 필드, 메소드 선언 시 그것이 최종상태가 되어 더이상 수정할 수 없다.

final 키워드를 클래스 앞에 붙이면 상속할 수 없다. 즉, final 클래스는 부모 클래스가 될 수 없고, 자식 클래스를 만들 수 없다. 그리고 final 키워드를 메소드 앞에 붙이면 오버라이딩할 수 없다.

 

protected 접근제한자

접근제한자의 순서는 제한이 약한순으로 비교했을 때, public, default, protected, private 이다.

protected는 default와 private 사이에 해당한다. 

같은 package에서는 접근을 허용하지만 다른 package에서는 자식클래스를 제외하고는 접근을 제한한다.

protected는 필드, 생성자, 메소드에만 적용될 수 있다.

 

타입변환과 다형성

다형성은 같은 타입이지만 실행 결과가 다양한 객체를 이용할 수 있는 성질을 말한다.

다형성을 위해 부모 클래스로 타입 변환을 허용한다.

상속관계에 있는 클래스 사이에서 타입변환이 발생한다. 자식이 부모로 자동변환되는 것을 업캐스팅, 자식이 부모로 자동형변환 되었던 것을 다시 강제로 자식으로 강제형변환하는 것이 다운캐스팅이다.

class Car {
	// 부모 클래스인 Tire클래스 자료형으로 자식타입의 객체들을 대입할 수 있다.
	Tire c1 = new HankookTire();
	Tire c2 = new KumhoTire();
	
	부모클래스 변수 = 자식클래스타입;
	// 자동타입변환이 일어난다.
}
//부모
class Animal {
}

//자식
class Cat {
}

// 표현방법 1
Cat cat = new Cat();
Animal animal = cat;

// 표현방법 2
Animal animal = new Cat();

표현방법 1에서 cat, 변수 animal은 Cat객체의 주소를 가리키고, Cat 객체는 Animal 객체를 상속받는다.

부모 타입으로 자동 타입변환된 이후에는 부모 클래스에 선언된 필드와 메소드만 접근이 가능하다.

만약 Animal 부모 클래스에 eat()메소드가 있고, Cat 자식 클래스에 run() 메소드가 있을 때를 보자.

//부모
class Animal {
	eat(){
	}
}

//자식
class Cat {
	run(){
  }
}

// 표현방법 1
Cat cat = new Cat();
Animal animal = cat;

cat.eat(); //ok
cat.run(); //ok
animal.eat(); //ok
animal.run(); // x

부모타입으로 자동 타입변환된 이후에는 부모 클래스에 선언된 필드와 메소드만 접근 가능하다.

변수는 자식 객체를 참조하지만, 변수로 접근 가능한 멤버는 부모 클래스 멤버로만 한정된다.

그러나 메소드가 자식 클래스에서 오버라이딩 되었다면, 자식 클래스의 메소드가 대신 호출된다.

 

//부모
class Animal {
	eat(){
	}
}

//자식
class Cat {
	run(){
  }
}

Cat cat = new Cat();
cat.eat(); // 자동타입변환
// Animal animal = cat;

부모의 메소드가 자식 클래스에서 오버라이딩 되어있다면 다형성의 성질에 의해 자식의 메소드가 호출된다.

메인 함수를 보면 자동 타입변환이 된 animal 객체에 자식클래스에서 오버라이딩된 메소드 eat()을 호출하니 자식클래스의 메소드가 호출된 것을 볼 수 있다.

 

- 부모 클래스

- 자식 클래스 (부모 클래스의 메소드인 eat()을 오버라이딩하였다)

 

- 메인함수

 

필드의 다형성

자식 클래스에서 부모 클래스의 메소드를 오버라이딩하면 해당 메소드를 호출 할 때, 부모의 메소드를 호출하지 않고 자식의 메소드를 호출한다.(위에있는 이미지)

자식타입은 부모타입으로 자동타입변환이 된다. (업캐스팅이라함)

 

매개변수의 다형성

자동타입변환은 메소드를 호출할 때 많이 발생한다.

자식 객체에서 부모 메소드를 사용한다면 자식 객체는 부모타입으로 자동타입변환이 발생한다. (업캐스팅)

매개값의 자동타입변환과 메소드 오버라이딩을 이용해서 매개변수의 다형성을 구현할 수 있다.

강제 타입변환

부모타입을 자식타입으로 바꾸는 것을 말한다. (다운캐스팅이라 한다.)

자식타입이 부모타입으로 자동 변환 후, 다시 자식 타입으로 변환하고 싶을 때 허용되는 타입변환이다.

자식클래스 변수 = (자식클래스) 부모클래스타입;
// 부모클래스타입은 자식 타입이 부모타입으로 자동변환된 상태였어야함

만약 자동타입변환에 의해 자식 타입이 부모타입으로 변환되었다고 하자. 그러면 그 객체는 자식클래스의 메소드를 사용할 수 없다.(부모타입이기 때문에)

따라서 자식 클래스의 메소드를 사용하기 위해서는 강제타입변환을 하여 자식 타입으로 바꿔줘야 한다. 

단, 여기서 자식 클래스에서 사용하고자 한 메소드를 이미 오버라이딩 했다면 자식클래스의 메소드가 호출됨으로 굳이 강제타입변환을 할 필요가 없다.

 

객체 타입 확인 instanceof 연산자

강제 타입변환은 자식타입이 부모타입으로 변환되어있는 상태에서만 가능하다.

부모타입의 변수가 자식을 참조하는 상태이면 강제 타입변환을 할 수 있다.

부모 변수가 참조하는 객체가 부모객체인지 자식 객체인지 확인하는 방법은 instanceof연산자를 사용하여 확인할 수 있다.

boolean result = 좌항(객체) instanceof 우항(타입)
boolean result = 1 instanceof char // false
boolean result = 1.0f instanceof float // true

 

추상클래스

abstract 키워드를 사용한다.

개발자에게 추상클래스를 상속받은 자식클래스에서 이미 선언된 추상메소드들을 의무적으로 오버라이딩하도록 하기 위해서 사용하는 개념이다.

public abstract class Car{
	public abstract void  Tire();
}

public class Tesla extends Car{
	@Override
	public void Tire(){
		System.out.println("전기자동차용 타이어");
	}
}
public class Volvo extends Car{
	@Override
	public void Tire(){
		System.out.println("트럭용 타이어");
	}
}

// 메인 클래스
Tesla model_s = new Tesla();
Volvo truck = new Volvo();

model_s.Tire();
// 출력 : 전기자동차용 타이어
truck.Tire();
// 출력 : 트럭용 타이어

Car car = null;
car = new Tesla();
car.Tire();
// 출력 : 전기자동차용 타이어
car = new Volvo();
car.Tire();
// 출력 : 트럭용 타이어

 

인터페이스

다중 상속 시 메소드 출처의 모호성 등의 문제가 발생하여 자바에서는 다중 상속을 허용하지 않는데, 그럼에도 불구하고 다중상속의 이점을 사용하기위해 인터페이스가 만들어졌다.

인터페이스란 : 다른 클래스를 작성할 때, 기본이 되는 틀을 제공하면서, 다른 클래스 사이의 중간 매개 역할까지 담당하는 일종의 추상클래스이다.

추상클래스는 추상메소드 뿐만 아니라 생성자, 필드, 일반 메소드도 포함할 수 있다.

하지만 인터페이스는 오로지 추상 메소드만 포함하고 있어야 한다.

 

이것이 자바다의 7장 상속을 공부하고 정리한 내용에 따로 찾아보면서 살을 붙인 내용이다.

'Java' 카테고리의 다른 글

소수 판별 & 상속  (0) 2022.10.21
자바 - 오버로딩 vs 오버라이딩  (0) 2022.06.10
자바 - 기타 제어자  (0) 2022.05.25
자바 - 메소드 오버로딩  (0) 2022.05.24
자바 - 기본 생성자  (0) 2022.05.17

댓글