기존 클래스에 기능 추가 및 재정의하여 새로운 클래스를 정의
부모 클래스: 상속 대상이 되는 기존 클래스 = 상위 클래스, 기초 클래스
자식 클래스 : 기존 클래스를 상속하는 클래스 = 하위 클래스, 파생 클래스
부모 클래스의 필드와 메소드가 상속됨 (생성자, 초기화 블록은 상속되지 않음)
(private 경우, 어디서나 접근이 불가능하므로 자식 클래스에서도 접근 불가하다. default의 경우, 같은 패키지의 자식 클래스는 접근 가능)
메소드의 선언부는 부모 클래스의 메소드와 동일해야 함
반환 타입에 한해, 부모 클래스의 반환 타입으로 형 변환할 수 있는 타입으로 변경 가능
부모 클래스의 메소드보다 접근제어자를 더 좁은 범위로 변경 불가
부모 클래스의 메소드보다 더 큰 범위의 예외 선언 불가
// Java 프로그래밍 - 상속
class Person {
String name;
int age;
public int a1;
private int a2;
Person() {} // 기본 생성자
Person(String name, int age) { // 초기화를 위해 만들어 준 오버라이딩 생성자
this.name = name;
this.age = age;
}
public void printInfo() {
System.out.println("Person.printInfo");
System.out.println("name: " + name);
System.out.println("age: " + age);
}
}
// Student 클래스 - Person 상속, 접근제어자 확인
class Student extends Person {
Student() {
a1 = 1;
// a2 = 1; -> private 이므로 상속을 받았지만, 다른 클래스라 적용이 안된다.
}
}
// Student 클래스 - Person 상속, super 사용, 오버라이딩
class Student2 extends Person {
String name;
int stdId;
Student2(String name, int age, int stdId) { // 생성자
// this.name = name; // 자기 객체의 name
// super.name = name; // 부모 객체 쪽의 변수 name
super(name, age); // 두 데이터를 부모 클래스 쪽으로 넘겨서 부모 클래스에서 초기화가 될 수 있도록 함
this.age = age; // 상속 받은 age (부모 클래스에만 존재하므로)
this.stdId = stdId; // 자기 객체의 stdId (부모 클래스에 없다.)
}
public void printInfo() {
System.out.println("Student2.printInfo");
System.out.println("name: " + name); // 기본적으로 자기 객체의 name을 받아서 쓴다. (but 자기 객체의 name에는 아무 값도 할당 되어있지 않다. 왜냐하면 super()을 통해 부모 클래스 쪽으로 name을 넘겼기 때문)
System.out.println("age: " + age);
System.out.println("stdId: " + stdId);
}
}
public class Main {
public static void main(String[] args) {
// Test code
// 1. 상속
System.out.println("=============");
Student s1 = new Student();
s1.name = "a";
s1.age = 25;
s1.printInfo();
// 2. super, super(), 오버라이딩
System.out.println("=============");
Student2 s2 = new Student2("b",32, 1);
s2.printInfo();
}
}
// Practice1
// 아래의 클래스 및 상속 관계에서 Test code를 수정하지 않고
// Cat 클래스 내에서 super 또는 super()를 이용하여
// "고양이 입니다." 가 출력될 수 있도록 변경해보세요.
class Animal {
String desc;
Animal() {
this.desc = "동물 클래스 입니다.";
}
Animal(String desc) {
this.desc = desc;
}
public void printInfo() {
System.out.println(this.desc);
}
}
class Cat extends Animal { // Animal 상속
String desc;
Cat() {
super.desc = "고양이 입니다."; // super 이용
super("고양이 입니다."); // super() 이용
}
}
public class Practice1 {
public static void main(String[] args) {
// Test code
Cat cat = new Cat();
cat.printInfo();
}
}
// Practice2
// 아래 클래스와 상속 관계에서
// Test code를 수정하지 않고, 아래와 같이 출력될 수 있도록 오버라이딩 해보세요.
// 빵빵!
// 위이잉!
// 빵빵!
// 삐뽀삐보!
class Car {
Car(){}
public void horn() {
System.out.println("빵빵!");
}
}
class FireTruck extends Car {
public void horn() {
super.horn(); // "빵빵!" 출력 (부모클래스 출력)
System.out.println("위이잉!");
}
}
class Ambulance extends Car {
public void horn() {
super.horn(); // "빵빵!" 출력 (부모클래스 출력)
System.out.println("삐뽀삐보!");
}
}
public class Practice2 {
public static void main(String[] args) {
// Test code
FireTruck truck = new FireTruck();
truck.horn();
Ambulance amb = new Ambulance();
amb.horn();
}
}