공통되는 부분이 있는경우 추상적인 부모를 두고 상속하는 것이 유용하다.
객체지향 프로그래밍의 핵심요소중 하나로, 기존 클래스의 필드와 메서드를 새로운 클래스에서 재사용하게 해준다. 이름 그대로 기존 클래스의 속성과 기능을 그대로 물려받는 것이다. 상속을 사용하려면 extends 키워드를 사용하며, 대상은 하나만 선택할 수있다.
용어정리
1) 부모 클래스(슈퍼 클래스): 상속을 통해 자신의 필드와 메서드를 다른 클래스에 제공하느 클래스
2) 자식 클래스(서브 클래스): 부모 클래스로부터 필드와 메서드를 상속받는 클래스
상속구조
자식이 부모의 기능을 물려받아 사용할 수 있다. 반대로 부모 클래스는 자식 클래스에 대한 정보가 없으므로 접근할 수 없다.
단일 상속
자바는 다중 상속을 지원하지 않는다. extend 대상은 하나만 선택할 수 있다. 부모가 또다른 부모를 하나 가지는 것은 괜찮다.
다중 상속을 지원하면 다이아몬드 문제(어떤 부모를 사용할지 애매), 클래스 계층 구조가 복잡해지는 문제가 발생한다. 따라서 자바는 다중상속을 허용하지 않는다.
Child clild = new clild();
//Child 는 Parent의 자식 클래스
//Child에는 chlidMethod(), Parent에는 parentMethod() 멤버 메서드가 있다.

new clild()를 호출하면 외부에서는 하나의 인스턴스를 생성하는 것 같지만 내부에서는 부모와 자식이 모두 생성되고 공간도 구분된다.
clild.chlidMethod() 호출시, 호출하는 변수의 타입(클래스 타입) 기준으로 Parent의인지, Child 인지 대상 타입을 찾는다.
clild.parentMethod() 호출시, 자식타입에 해당 기능이 없으면 부모타입으로 올라가서 찾는다. (부모한테서도 찾지 못하면 컴파일 오류)
부모에 기능을 한번만 추가하면 자식 클래스들에 일일히 기능을 추가하지 않아도 된다.
자식은 부모 기능 외 필요한 부분을 extend(확장) 하기만 하면 된다.
protected 는 다른 패키지에서 접근 불가이나, 상속시에는 접근 가능하다.
본인 타입에 없으면 부모타입에서 기능을 찾는데, 객체 내부에서는 자식과 부모가 구분되어 있으므로 접근제어자가 영향을 준다. 부모입장에서는 외부에서 호출한 것과 같다.
package extends1.access.parent;
public class Parent {
public int publicValue;
protected int protectedValue;
int defaultValue;
private int privateValue;
public void publicMethod() {
System.out.println("Parent.publicMethod");
}
protected void protectedMethod() {
System.out.println("Parent.protectedMethod");
}
void defaultMethod() {
System.out.println("Parent.defaultMethod");
}
private void privateMethod() {
System.out.println("Parent.privateMethod");
}
public void printParent() {
System.out.println("==Parent 메서드 안==");
System.out.println("publicValue = " + publicValue);
System.out.println("protectedValue = " + protectedValue);
System.out.println("defaultValue = " + defaultValue); //부모 메서드 안에서 접근 가능
System.out.println("privateValue = " + privateValue); //부모 메서드 안에서 접근 가능
//부모 메서드 안에서 모두 접근 가능
defaultMethod();
privateMethod();
}
}
package extends1.access.chlid;
public class Child extends Parent {
public void call() {
publicValue = 1;
protectedValue = 1; //상속 관계 or 같은 패키지
//defaultValue = 1; //다른 패키지 접근 불가, 컴파일 오류
//privateValue = 1; //접근 불가, 컴파일 오류
publicMethod();
protectedMethod(); //상속 관계 or 같은 패키지
//defaultMethod(); //다른 패키지 접근 불가, 컴파일 오류
//privateMethod(); //접근 불가, 컴파일 오류
printParent();
}
}
부모와 자식의 필드명이 같거나 메서드가 오버라이딩 되어있으면, 자식에서 부모의 필드나 메서드를 호출할 수 없다. 이때 super 키워드를 사용하면 부모를 참조할 수있다. super는 이름 그대로 부모 클래스에 대한 참조를 나타낸다.
public class Child extends Parent {
public String value = "child";
@Override
public void hello() {
System.out.println("Child.hello");
}
public void call() {
System.out.println("this value = " + this.value); //this 생략 가능
System.out.println("super value = " + super.value);// 부모참조
this.hello(); //this 생략 가능
super.hello();// 부모참조
}
}
상속 관계를 사용하면 자식 클래스의 생성자에서 부모 클래스의 생성자를 반드시 호출해야 한다.(규칙)
상속관게에서 부모의 생성자를 호출할 때는 super(..) 를 사용
1. ClassA 는 최상위 부모 클래스이다.
public class ClassA {
public ClassA() {
System.out.println("ClassA 생성자");
}
}
public class ClassB extends ClassA {
public ClassB(int a) {
super(); //부모클래스 생성자가 기본 생성자이므로 생략 가능
System.out.println("ClassB 생성자 a=" + a);
}
public ClassB(int a, int b) {
super(); //부모클래스 생성자가 기본 생성자이므로 생략 가능
System.out.println("ClassB 생성자 a=" + a + " b=" + b);
}
}
public class ClassC extends ClassB {
public ClassC() {
super(10, 20);
System.out.println("ClassC 생성자");
}
}
ClassA -> ClassB -> ClassC 순서로 실행된다.public class Super2Main {
public static void main(String[] args) {
ClassC classC = new ClassC();
}
}

public class ClassB extends ClassA {
public ClassB(int a) {
this(a, 0); //this를 생성자 첫줄에 써주더라도 언젠가 반드시 자식 생성자 안에서 super()를 호출 필요
System.out.println("ClassB 생성자 a=" + a);
}
public ClassB(int a, int b) {
super(); // super()를 호출
System.out.println("ClassB 생성자 a=" + a + " b=" + b);
}
}
main
public class Super2Main {
public static void main(String[] args) {
// ClassC classC = new ClassC();
ClassB classB = new ClassB(100);
}
}
출력결과
ClassA -> ClassB -> ClassB(첫줄 this( a, 0 )인 생성자) 순서로 실행

Item 클래스에서 기본 기능을 제공하기 때문에
Book과 같은 자식클래스는 기본 기능을 super로 가져다 쓰고
개별 속성이나 기능만 신경쓰면 된다.
public class Item {
private String name;
private int price;
public Item(String name, int price){
this.name = name;
this.price = price;
}
public int getPrice(){
return price;
}
public void print() {
system.out.println("이름:" + name +", 가격:" + price)
}
}
public class Book extends Item {
private String author;
private String isbn;
public Book(String name, int price, String author, String isbn) {
super(name, price); //생성자 첫줄 super(...)로 부모 생성자 호출
this.author = author;
this.isbn = isbn;
}
@Override
public void print() {
super.print(); // private 선언 부모 멤버변수는 접근불가. 부모 메서드는 public이므로 super로 메서드 호출
System.out.println("- 저자:"+ author + ", isbn:" + isbn);
}
}