두 클래스가 상속관계에 있을 때 하위 클래스는 상위 클래스가 가진 모든 멤버를 상속받는다.
따라서 하위클래스의 멤버는 상위클래스보다 멤버 개수가 같거나 많다.
위 그림을 상속의 맥락에서 설명해보면 인간 클래스가 상위클래스이고 선생님, 학생, 직장인은 상위 클래스(인간)로부터 특정한 속성(이름,나이,키)과 기능(밥,걸음)을 내려받는 하위클래스이다.
상속을 사용하는 이유
- 코드를 재사용하여 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있어 코드의 중복을 제거한다.
- 다형적 표현이 가능하다.
※다형성이란 하나의 객체가 여러 모양으로 표현될 수 있다. 다형성은 객체지향형 프로그래밍의 핵심적이고 중요한 개념이다.
ex)'학생은 학생이다.' -> '학생은 인간이다.'
package com.sparta.algorithm.practice;
public class HelloJava {
public static void main(String[] args) {
Person person = new Person();
person.name = "김계란";
person.eat();
System.out.println(person.name);
Programmer programmer = new Programmer();
programmer.name = "김코딩";
programmer.age = 28;
programmer.companyName = "코드거츠";
programmer.coding();
programmer.walk();
programmer.eat();
programmer.learn();
System.out.println(programmer.companyName);
Dancer dancer = new Dancer();
dancer.name = "블랙핑크";
dancer.age = 28;
dancer.groupName = "JYP";
Singer singer = new Singer();
singer.name = "김범수";
singer.age = 40;
singer.bandName = "나가수";
}
}
주의할 것은 자바의 객체지향 프로그래밍에서는 단일 상속(single inheritance)만을 허용하는데 다중 상속은 허용하지 않는다라는 것을 꼭 기억해야한다.
포함은 상속처럼 클래스를 재사용할 수 있는 방법. 클래스의 멤버로 다른 클래스 타입의 참조변수를 선언하는 것
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;
}
}
// 출력값
1 김코딩
서울 한국
2 박해커
도쿄 일본
Address 클래스로 해당 변수들을 묶어주고 Employee 클래스 안에 참조변수(Address address)를 선언하는 방법으로 코드의 중복을 없애고 포함관계로 재사용하고 있다.
상속과 포함관계를 구분할 수 있는 방법
- 클래스 간의 관계는 '~은 ~이다.'(Is-A) 관계인지 '~은 ~을 가지고 있다'(Has-A) 관계인지 구분하면 된다.
ex) '학생은 인간이다' -> Is-A 관계 // '종업원은 주소를 가지고 있다.' -> Has-A 관계
※오버라이딩한 메소드의 우선순위가 더 높다.
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();
}
}
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
위 예시를 보면 Vehicle 클래스에 run() 메소드가 있는데 Bike, Car, MotorBike 클래스에서 run() 메소드를 재정의 하는데 Vehicle 클래스의 run()메서드를 오버라이딩 하고 있다.
메서드 오버라이딩은 상위 클래스에 정의된 메서드를 하위 클래스에 맞는 메서드 동작을 하고자 할 때 사용한다.
오버라이딩의 조건
1. 메서드의 선언부(이름, 매개변수, 반환타입)이 상위클래스의 메서드와 완전히 일치해야된다.
2. 접근 제어자의 범위가 상위클래스의 메서드보다 같거나 넓어야 한다.
ex)Vehicle의 run 메소드는 protect인데 Car의 run 메소드가 private면 에러가 발생
3. 예외는 상위 클래스의 메서드보다 많이 선언할 수 없다.
super 키워드는 상위 클래스의 객체 , super()는 상위 클래스의 생성자를 호출하는 것
public class Example {
public static void main(String[] args) {
SubClass subClassInstance = new SubClass();
subClassInstance.callNum();
}
}
class SuperClass {
int count = 20; // super.count
}
class SubClass extends SuperClass {
int count = 15; // this.count
void callNum() {
System.out.println("count = " + count);
System.out.println("this.count = " + this.count);
System.out.println("super.count = " + super.count);
}
}
// 출력값
count = 15
count = 15
count = 20
**상위 클래스의 변수를 참조해야 할 경우가 생기면 super 키워드를 통해 부모의 객체의 멤버 값을 참고할 수 있다.
public class HelloJava {
public static void main(String[] args) {
Programmer p = new Programmer();
}
}
public class Person {
Person(){
System.out.println("Person 클래스 생성자");
}
}
public class Programmer extends Person{
Programmer(){
super(); // Person 클래스의 생성자 호출 -> Person클래스 생성자
System.out.println("프로그래머 클래스 생성자");
}
}
super 메서드는 this()와 마찬가지로 생성자 안에서만 사용가능하고, 반드시 첫줄에 와야한다.
👉자바의 모든 클래스는 Object 클래스로부터 확장된다
class ParentEx { // 컴파일러가 "extends Object" 자동 추가
}
class ChildEx extends ParentEx {
}
Object 클래스, 가장 위에 위치하기 때문에 Object 클래스의 멤버들을 자동으로 상속받아 사용가능하다.