extends
키워드를 사용하여 두 개 이상의 클래스 간 상속 관계를 정의할 수 있다.super
와 super()
의 차이를 설명할 수 있다.기존의 클래스를 재활용해서 새로운 클래스를 작성하는 자바의 문법
이때 상속 관계에 있는 두 클래스를 상위 클래스
, 하위 클래스
라고 말한다.
하위 클래스
는 상위 클래스
가 가진 모든 멤버(필드, 메서드, 이너 클래스)를 상속 받는다.
따라서 하위 클래스
의 멤버 개수는 상위 클래스
보다 많거나 같고, "상위 클래스
로부터 확장되었다!" 라는 표현을 쓴다.
extends
키워드를 사용
하위 클래스
는 상위 클래스
가 가진 모든 멤버(필드, 메서드, 이너 클래스)를 상속 받는다.
(하지만 상위 클래스의 생성자는 상속되지 않는다.)
하위 클래스
의 멤버 개수는 항상 상위 클래스
보다 많거나 같다.
단일 상속만을 허용 (다중 상속은 불가!)
=> 하지만 인터페이스
를 통해서 다중 상속과 비슷한 효과가 일어나긴 한다.
상위 클래스의 접근 제어가 private이나 default로 설정된 멤버는 하위 클래스에서 상속받지만 접근할 수는 없습니다.
코드의 중복을 제거
❓ 다형적 표현이란?
💁♀️ 하나의 객체가 여러 모양으로 표현될 수 있다는 것을 다형성이라고 한다.
클래스의 멤버로 다른 클래스의 참조 변수를 선언하는 것
(내부 클래스가 아닌 경우도 O)
public class Employee {
int id;
String name;
Address address;
public Employee(int id, String name, Address address) {
this.id = id;
this.name = name;
this.address = address;
}
void showInfo() {
System.out.println(id + " " + name);
System.out.println(address.city+ " " + address.country);
}
public static void main(String[] args) {
Address address1 = new Address("서울", "한국");
Address address2 = new Address("도쿄", "일본");
Employee e = new Employee(1, "김코딩", address1);
Employee e2 = new Employee(2, "박해커", address2);
e.showInfo();
e2.showInfo();
}
}
class Address {
String city, country;
public Address(String city, String country) {
this.city = city;
this.country = country;
}
}
Employee 클래스의 멤버로, Address 클래스의 참조변수가 존재한다.
상속
: ~은 ~이다(IS-A) 포함
: ~은 ~을 가지고 있다.(HAS-A)
상위 클래스
로부터 상속받은 메서드를 재정의 하는 것
** Override = "덮어쓰다"
(2,3번은 몰랐던 내용이라 추가 학습이 필요할 것 같다!)
상위 클래스
로부터 상속받은 메서드를 다른 방식으로 사용하기 위해서
ex) toString()
public class Main {
public static void main(String[] args) {
Bike bike = new Bike(); // 각각의 타입으로 선언 + 각각의 타입으로 객체 생성
Car car = new Car();
MotorBike motorBike = new MotorBike();
bike.run();
car.run();
motorBike.run();
Vehicle bike2 = new Bike(); // 상위 클래스 타입으로 선언 + 각각 타입으로 객체 생성
Vehicle car2 = new Car();
Vehicle motorBike2 = new MotorBike();
bike2.run();
car2.run();
motorBike2.run();
}
}
class Vehicle {
void run() {
System.out.println("Vehicle is running");
}
}
class Bike extends Vehicle {
void run() {
System.out.println("Bike is running");
}
}
class Car extends Vehicle {
void run() {
System.out.println("Car is running");
}
}
class MotorBike extends Vehicle {
void run() {
System.out.println("MotorBike is running");
}
}
// 출력값
Bike is running
Car is running
MotorBike is running
Bike is running
Car is running
MotorBike is running
아래 코드와 같이, 각 하위 클래스
객체를 상위 클래스
타입으로 선언하고 오버라이딩된 메서드를 호출하면 원본 메서드가 아닌, 각 하위 클래스
에 재정의된 오버라이딩 메서드들이 호출된다.
Vehicle bike2 = new Bike(); // 상위 클래스 타입으로 선언 + 각각 타입으로 객체 생성
Vehicle car2 = new Car();
Vehicle motorBike2 = new MotorBike();
bike2.run();
car2.run();
motorBike2.run();
// 출력
Bike is running
Car is running
MotorBike is running
그러므로 여러 하위 클래스
들의 객체를 모두 상위 클래스
타입의 배열로 선언하면, 간편하게 이들을 관리할 수 있다.
Vehicle[] vehicles = new Vehicle[] { new Bike(), new Car(), new MotorBike()};
for (Vehicle vehicle : vehicles) {
vehicle.run();
}
super/super()의 관계는 이전에 배웠던 this/this()의 관계와 비슷하다.
this: 자신의 객체를 가리킴
this(): 자신의 생성자를 호출
super: 상위 클래스의 객체를 가리킴
super(): 상위 클래스의 생성자를 호출
public class Main {
public static void main(String[] args) {
Lower l = new Lower();
l.callNum();
}
}
class Upper {
int count = 20; // super.count
}
class Lower extends Upper {
int count = 15; // this.count
void callNum() {
System.out.println("count = " + count); // (this.)count
System.out.println("this.count = " + this.count);
System.out.println("super.count = " + super.count);
}
}
// 출력값
count = 15
this.count = 15
super.count = 20
✅
super
나this
키워드를 붙이지 않으면, 자신의 속한 인스턴스 객체의 멤버를 먼저 참조한다!
public class Main {
public static void main(String[] args) {
Student s = new Student();
}
}
class Human {
Human() {
System.out.println("휴먼 클래스 생성자");
}
}
class Student extends Human { // Human 클래스로부터 상속
Student() {
super(); // Human 클래스의 생성자 호출
System.out.println("학생 클래스 생성자");
}
}
super
는 반드시 생성자 안에서만 사용 가능하다.this()
또는 super()
가 선언되어야 한다.super()
가 없는 경우에는, 컴파일러 생성자의 첫 줄에 자동으로 super()
를 삽입한다.✅ 클래스를 만들 때는 기본 생성자를 생성하는 것을 꼭 습관화 하자!
자바의 최상위 클래스
➡️ 모든 클래스는 Object 클래스를 상속받는다.