package extends1.ex;
package extends1.ex1;
public class ElectricCar {
public void move() {
System.out.println("차를 이동합니다.");
}
public void charge() {
System.out.println("충전합니다.");
}
}
package extends1.ex1;
public class GasCar {
public void move() {
System.out.println("차를 이동합니다.");
}
public void fillUp() {
System.out.println("기름을 주유합니다.");
}
}
public class CarMain {
public static void main(String[] args) {
ElectricCar electricCar = new ElectricCar();
electricCar.move();
electricCar.charge();
GasCar gasCar = new GasCar();
gasCar.move();
gasCar.FillUp();
}
}

객체 지향 요소 프로그래밍의 핵심 요소 중 하나로, 기존 클래스의 필드와 메서드를 새로운 클래스에서 재사용하게 해준다. 이름 그대로 기존 클래스의 속성과 기능을 그대로 물려받는 것. 상속을 사용하려면 extends 키워드를 사용. extends 대상은 하나만 선택가능
부모 클래스(슈퍼 클래스) : 상속을 통해 자신의 필드와 매소드를 다른 클래스에 제공하는 클래스
자식 클래스(서브 클래스) : 부모 클래스로부터 필드와 메서드를 상속받는 클래스
package extends1.ex2;
public class Car {
public void move() {
System.out.println("차를 이동합니다.");
}
}
package extends1.ex2;
public class ElectricCar extends Car {
public void charge() {
System.out.println("충전합니다.");
}
}
package extends1.ex2;
public class GasCar extends Car {
public void fillUp() {
System.out.println("기름을 주유합니다.");
}
}

자바는 다중 상속을 지원하지 않는다. extend 대상은 하나만 선택 가능




개념정리를 잘해둬야 함. 뒤에서 다형성을 이해하는데 큰 도움이 됨.

기존 코드를 유지하기 위해 ex3 패키지를 새로 만들자
package extends1.ex3;
public class Car {
public void move() {
System.out.println("차를 이동합니다.");
}
//추가
public void openDoor() {
System.out.println("문을 엽니다.");
}
}
package extends1.ex3;
//추가
public class HydrogenCar extends Car {
public void fillHydrogen() {
System.out.println("수소를 충전합니다.");
}
}
package extends1.ex3;
public class CarMain {
public static void main(String[] args) {
ElectricCar electricCar = new ElectricCar();
electricCar.move();
electricCar.charge();
electricCar.openDoor();
GasCar gasCar = new GasCar();
gasCar.move();
gasCar.fillUp();
gasCar.openDoor();
HydrogenCar hydrogenCar = new HydrogenCar();
hydrogenCar.move();
hydrogenCar.fillHydrogen();
hydrogenCar.openDoor();
}
}

부모타입의 기능을 자식이 다르게 저장하고 싶은 경우
package extends1.overriding;
public class ElectricCar extends Car {
@Override
public void move() {
System.out.println("전기차를 빠르게 이동합니다.");
}
public void charge() {
System.out.println("충전합니다.");
}
}
안써도 문제는 없다. 하지만 코드의 명확성을 보여주므로 그냥 쓰자.

메서드 오버로딩 : 메서드 이름이 같고 매개변수(파라미터)가 다른 메
서드를 여러 개 정의 하는 것, 같은 이름의 메서드를 여러개 정의했다고 이해하면 편함.
메서드 오버라이딩 : 하위 클래스에서 상위 클래스의 메서드를 재정의하는 과정, 자식의 새로운 기능이 부모의 기존 기능을 넘어 타서 새로운 기능으로 덮어버린다고 이해하면 편함.
메서드 이름: 메서드 이름이 같아야 한다.
메서드 매개변수(파라미터): 매개변수(파라미터) 타입, 순서, 개수가 같아야 한다.
반환 타입: 반환 타입이 같아야 한다. 단 반환 타입이 하위 클래스 타입일 수 있다.
접근 제어자: 오버라이딩 메서드의 접근 제어자는 상위 클래스의 메서드보다 더 제한적이어서는 안된다. 예를 들어, 상위 클래스의 메서드가 protected 로 선언되어 있으면 하위 클래스에서 이를 public 또는 protected 로 오버라이드할 수 있지만, private 또는 default 로 오버라이드 할 수 없다.
예외: 오버라이딩 메서드는 상위 클래스의 메서드보다 더 많은 체크 예외를 throws 로 선언할 수 없다. 하지만 더 적거나 같은 수의 예외, 또는 하위 타입의 예외는 선언할 수 있다. 예외를 학습해야 이해할 수 있다. 예외는 뒤에서 다룬다.
static , final , private : 키워드가 붙은 메서드는 오버라이딩 될 수 없다.
생성자 오버라이딩: 생성자는 오버라이딩 할 수 없다.

순서대로 private 이 가장 많이 차단하고, public 이 가장 많이 허용한다.
private -> default -> protected -> public
= 부모 클래스의 참조
package extends1.super1;
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();
super.hello();
}
}
package extends1.super1;
public class Parent {
public String value = "parent";
public void hello() {
System.out.println("Parent.hello");
}
}
package extends1.super1;
public class Super1Main {
public static void main(String[] args) {
Child child = new Child();
child.call();
}
}

package extends1.super2;
public class ClassA {
public ClassA() {
System.out.println("ClassA 생성자");
}
}
package extends1.super2;
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);
}
}
package extends1.super2;
public class ClassC extends ClassB{
public ClassC() {
super(10,20);
System.out.println("ClassC 생성자");
}
}
package extends1.super2;
public class Super2Main {
public static void main(String[] args) {
ClassC classC = new ClassC();
}
}

- 상속 관계의 생성자 호출은 결과적으로 부모에서 자식 순서로 실행된다. 따라서 부모의 데이터를 먼저 초기화하고 그 다음에 자식의 데이터를 초기화한다.
- 상속 관계에서 자식 클래스의 생성자 첫줄에 반드시 super를 호출해야 한다. 단 기본 생성자(super)인 경우 생략 할 수 있다.
클래스에 final
메서드에 final