부모클래스(상위클래스)의 필드(field)
와 메서드(method)
를 자식 클래스(하위 클래스)가 물려 받아서 그대로 사용 할 수 있는것.
자식 클래스가 extends
키워드를 사용하여 상속할 부모 클래스를 지정한다.
class 자식클래스 extends 부모클래스 {
// 필드
// 생성자
// 메서드
}
추상화
필드(field)
와 메서드(method)
를 물려받아서 유지 보수를 쉽도록 하기 위함.
자식 클래스를 이용해서 자식 객체를 생성하면, 내부적으로 부모 객체가 먼저 생성되고 자식 객체가 그 다음에 생성된다.
자식 클래스의 객체를 생성할때 생성자가 명시적으로 선언되어있지 않다면 컴파일러는 super( )
메서드를 사용하여 부모 클래스의 기본 생성자를 생성한다. 이때 super( ) 메서드는 반드시 자식 생성자 첫 줄에 위치해야한다.
자식클래스 인스턴스변수 = new 자식클래스();
public 자식클래스() {
super();
}
public 부모클래스() {
}
ex) 부모 생성자 호출 예시
public class CellPhone { // CellPhone : 부모클래스
public String name;
public String number;
public CellPhone(String name, String number) {
this.name = name;
this.number = number;
}
}
public class DmbCellPhone extends CellPhone { // DmbCellPhone : 자식클래스
public int price;
public DmbCellPhone(String name, String number, int size) {
super(name, number);
this.price = price;
}
}
public class DmbCellPhoneEx {
public static void main(String[] args) {
DmbCellPhone dcp = new DmbCellPhone("갤럭시", "010-1111-2222", 1000);
System.out.println("name = " + dcp.name); // name = 갤럭시 (부모클래스에서 상속받은 필드 출력)
System.out.println("number = " + dcp.number); // number = 010-1111-2222 (부모클래스에서 상속받은 필드 출력)
System.out.println("price = " + dcp.price); // price = 1000
}
}
부모 클래스에게 물려받은 메서드를 자식 클래스에서 @Override
를 이용하여 다시 수정하는것.
메서드가 오버라이딩 되었을때 자식 객체에서 메서드를 호출하면 된다면 부모 객체의 메서드는 숨겨지고 자식 메서드가 호출된다.
1) 오버라이딩된 자식 메서드는 부모 메서드와 동일한 시그니처(반환타입
, 메서드이름
, 매개변수
)를 가져야한다.
2) 접근 제한자를 더 강하게 오버라이딩 할 수 없다. (반대는 가능)
ex1) 부모메서드가 public 접근제한을 갖고 있을 때 오버라이딩된 자식메서드는 default나 private 접근제한을 가질 수 없다. (x)
ex2) 부모메서드가 default 접근제한을 갖고 있을 때 오버라이딩된 자식메서드는 default나 public 접근제한을 가질 수 있다. (o)
3) 새로운 예외(Exception)를 throws 할 수 없다.
자식 클래스에서 부모 클래스의 메서드를 오버라이딩하게 되면, 부모 클래스의 메서드는 숨겨지고 오버라이딩된 자식 메서드만 사용된다.
그런데 만약 자식 클래스 내부에서 부모 클래스의 메서드를 호출해야 한다면 super.부모메서드( );
로 부모 메서드를 호출 할 수 있다.
public class Airplane { // Airplane : 부모클래스
public void land() {
System.out.println("착륙한다");
}
public void fly() {
System.out.println("일반 비행한다");
}
public void takeOff() {
System.out.println("이륙한다");
}
}
public class SupersoicAirplane extends Airplane { // SupersoicAirplane : 자식클래스
public static final int NORMAL = 1;
public static final int SUPERSONIC = 2;
public int flyMode = NORMAL;
@Override
public void fly() {
if(flyMode == SUPERSONIC) {
System.out.println("음속 비행한다");
}else {
super.fly(); // Airplane 부모클래스의 fly() 메서드 호출
}
}
}
public class SupersoicAirplaneEx {
public static void main(String[] args) {
SupersoicAirplane sa = new SupersoicAirplane();
sa.takeOff(); // 이륙한다
sa.fly(); // 일반 비행한다
sa.flyMode = SupersoicAirplane.SUPERSONIC;
sa.fly(); // 음속 비행한다
sa.flyMode = SupersoicAirplane.NORMAL;
sa.fly(); // 일반 비행한다
sa.land(); // 착륙한다
}
}
다른객체의 인스턴스를 자신의 인스턴스 변수로 포함해서 메서드를 호출하는것
상속과 컴포지션의 예시
class Engine {
int power = 2000;
}
class Car {
Engine e; // 가져와서 사용하는것 --> 컴포지션 (=결합)
public Car(Engine e) { // 생성자
this.e = e;
}
}
class Hamburger {
String name ="기본햄버거";
String material1 = "양상추";
String material2 = "패티";
}
class CheeseHamburger extends Hamburger { // 상속가능 (상태, 행위 물려받을수 있음. 타입이 일치해야된다.)
String name = "치즈햄버거";
}
class ChickenHamburger {
Hamburger h; // 가져와서 사용하는것 --> 컴포지션 (=결합)
String name = "치킨햄버거";
public ChickenHamburger(Hamburger h) { // 생성자
this.h = h;
}
}
public class OOPEX02 {
public static void main(String[] args) {
Engine e1 = new Engine();
Car c1 = new Car(e1);
System.out.println("자동차 엔진 마력 : " + c1.e.power);
CheeseHamburger ch1 = new CheeseHamburger();
System.out.println("햄버거 이름 : " + ch1.name);
System.out.println("재료들 이름 : " + ch1.material1 + ", " + ch1.material2);
Hamburger h1 = new Hamburger();
ChickenHamburger ckh1 = new ChickenHamburger(h1);
System.out.println("햄버거 이름 : " + ckh1.name);
System.out.println("재료들 이름 : " + ckh1.h.material1 + ", " + ckh1.h.material2);
}
}
타입이 일치할 경우 상속을 받거나 컴포지션을 통해서 재사용 할 수 있다.
출처
- 이지업 컨텐츠 내의 데어프로그래밍 자바강의
- 이것이 자바다 (책)