상속의 장점
상속 구조
자식클래스 extends 부모클래스
public class Person {
public void eat() { }
public void sleep() { }
public void walk() { }
}
// 서브클래스 // 슈퍼클래스
public class Student extends Person {
public void study() { }
}
// 서브클래스 // 슈퍼클래스
public class Researcher extends Person {
public void research() { }
}
// 서브클래스 // 슈퍼클래스
public class Professor extends Researcher {
public void teach() { }
}
학생 is a 사람 [ 상속 ]
슈퍼클래스인 Person은 eat(), sleep(), walk() 메소드 3개를 사용할 수 있다.
package ex01_is_a;
// 부모
public class Person {
public void eat() {
System.out.println("먹는다");
}
public void sleep() {
System.out.println("잔다");
}
public void walk() {
System.out.println("걷는다");
}
}
서브클래스인 Student 내부에는 study() 메소드 1개만 정의돼 있지만, 슈퍼클래스로부터 받은 메소드가 있어 eat(), sleep(), walk() 메소드 3개도 사용할 수 있다.
package ex01_is_a;
// 자식 부모
public class Student extends Person {
public void study() {
System.out.println("공부한다");
}
}
student 객체에 있는 메소드들을 호출했다.
package ex01_is_a;
public class StudentMain {
public static void main(String[] args) {
Student student = new Student();
student.eat(); // 먹는다
student.sleep(); // 잔다
student.walk(); // 걷는다
student.study(); // 공부한다
}
}
전기차 is a 승용차
하이브리드 is a 전기차 [ 상속 ]
상위클래스인 Car는 drive() 메소드 1개를 사용할 수 있다.
package ex02_is_a;
public class Car {
public void drive() {
System.out.println("달린다");
}
}
하위클래스인 Ev 내부에는 charge() 메소드 1개만 정의돼 있지만, 상위클래스로부터 받은 메소드가 있어 drive() 메소드 1개도 사용할 수 있다.
package ex02_is_a;
public class Ev extends Car {
public void charge() {
System.out.println("충전한다");
}
}
하위클래스인 Hybrid 내부에는 addOil() 메소드 1개만 정의돼 있지만, 상위클래스로부터 받은 메소드가 있어 drive(), charge() 메소드 2개도 사용할 수 있다.
package ex02_is_a;
public class Hybrid extends Ev {
public void addOil() {
System.out.println("기름을 넣는다");
}
}
hybrid 객체에 있는 메소드들을 호출했다.
package ex02_is_a;
public class HybridMain {
public static void main(String[] args) {
Hybrid hybrid = new Hybrid();
hybrid.drive(); // 달린다
hybrid.charge(); // 충전한다
hybrid.addOil(); // 기름을 넣는다
}
}
군인 has a 총
package ex01_has_a;
public class Gun {
// 필드
private String model;
private int bullet;
private final int MAX_BULLET = 15;
// 메소드
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public int getBullet() {
return bullet;
}
public void setBullet(int bullet) {
this.bullet = bullet;
}
// 장전
public void reload(int bullet) {
if(this.bullet == MAX_BULLET) {
return;
}
this.bullet += bullet;
this.bullet = (this.bullet > MAX_BULLET) ? MAX_BULLET : this.bullet;
// 만약 15발이 넘었다면, 15발로
}
// 총쏘기
public void shoot() {
if(bullet == 0) {
return;
}
bullet--;
}
}
package ex01_has_a;
public class Soldier {
// 필드
private Gun gun;
// 메소드
public Gun getGun() {
return gun;
}
public void setGun(Gun gun) {
this.gun = gun;
}
public void reload(int bullet) {
gun.reload(bullet); // 장전하다
}
public void shoot() {
gun.shoot(); // 총쏘기
}
}
package ex01_has_a;
public class SoldierMain {
public static void main(String[] args) {
Gun gun = new Gun();
gun.setModel("K2");
gun.setBullet(9);
Soldier soldier = new Soldier();
soldier.setGun(gun);
// soldier가 총을 쏜다
soldier.shoot();
// soldier가 장전한다
soldier.reload(1);
// soldier가 가지고 있는 gun의 model
System.out.println(soldier.getGun().getModel()); // K2
System.out.println(soldier.getGun().getBullet()); // 9
}
}
Gun의 모델명은 K2이고,
총알은 9발이 있었는데 1번 총을 쏘고 나서, 1발 장전했기 때문에 9발이 남았다.
군인 has a 총 [ 상속 ]
package ex02_has_a;
public class Gun {
// 필드
private String model;
private int bullet;
private final int MAX_BULLET = 15;
// 메소드
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public int getBullet() {
return bullet;
}
public void setBullet(int bullet) {
this.bullet = bullet;
}
// 장전
public void reload(int bullet) {
if(this.bullet == MAX_BULLET) {
return;
}
this.bullet += bullet;
this.bullet = (this.bullet > MAX_BULLET) ? MAX_BULLET : this.bullet;
// 만약 15발이 넘었다면, 15발로
}
// 총쏘기
public void shoot() {
if(bullet == 0) {
return;
}
bullet--;
}
}
Gun 상위클래스를 그대로 상속 받는다.
package ex02_has_a_inherit;
// Soldier has a Gun.
public class Soldier extends Gun {
}
package ex02_has_a_inherit;
public class SoldierMain {
public static void main(String[] args) {
Soldier soldier = new Soldier();
soldier.reload(10);
soldier.shoot();
System.out.println(soldier.getBullet()); // 9
}
}
10발을 장전했고, 총을 1번 쌌기 때문에 총알은 9발이 남았다.
서브클래스의 객체 생성
- 서브클래스의 객체는 슈퍼클래스의 메소드를 사용 가능
- 서브클래스의 객체를 생성할 때 슈퍼클래스의 객체가 먼저 생성
public class Person {
public Person() {
System.out.println("Person 생성");
}
}
public class Student extends Person {
public Student(){
System.out.println("Student 생성");
}
}
public class Ex {
public static void main(String[] args) {
Student student = new Student();
} // Student()만 불렀는데 슈퍼클래스인 Person() 자동으로 불림
// 디폴트 형태만 가능(매개변수가 아무것도 없는 타입)
}
실행결과
Person 생성
Student 생성
부모 없는 자식이 태어날 수 없으니, 자식이 만들어지려면 부모가 있어야 한다. 그래서 자동으로 자식을 만들려면
슈퍼클래스의 생성자인 Person 생성
이 먼저 호출되고, 그 다음에 서브클래스의 생성자인 Student 생성
가 호출된다.
부모클래스의 디폴트 생성자를 호출하는 경우
package ex01_constructor;
public class Person {
public Person() {
System.out.println("Person 생성");
}
}
package ex01_constructor;
// 서브클래스는 슈퍼클래스의 생성자를 "반드시" 호출해야 한다.
// (자식이 태어나려면 부모가 태어나 있어야 한다.)
public class Student extends Person{
// 개발자가 슈퍼클래스의 생성자를 호출하지 않으면
// 자동으로 JVM이 호출한다. (default 형식(매개변수X)의 슈퍼클래스만 자동 호출 가능)
public Student() {
System.out.println("Student 생성");
}
}
package ex01_constructor;
public class StudentMain {
public static void main(String[] args) {
Student student = new Student(); // Person 생성
// 서브클래스 생성자 호출 // Student 생성
}
}
부모클래스의 디폴트가 아닌 생성자를 호출하는 경우
package ex02_constructor;
public class Person {
private String name;
public Person(String name) {
this.name = name;
} // 여기까지 작성하고 getter/setter 실행
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package ex02_constructor;
// default 형식이 아니라서 빨리 슈퍼클래스의 생성자를 호출하라고 오류가 뜬다.
public class Student extends Person {
private String school;
public Student(String name, String school) {
super(name); // 슈퍼클래스의 생성자인 Person을 "super"라고 부른다.
this.school = school;
} // 여기까지 작성하고 getter/setter 실행
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
}
package ex02_constructor;
public class StudentMain {
public static void main(String[] args) {
Student student = new Student("tom", "goodee");
System.out.println(student.getName()); // tom
System.out.println(student.getSchool()); // goodee
}
}
학교 다니면서 도서관에서 아르바이트 하는 학생이 있다.
- 클래스 Alba
- 필드 String company;
package ex02_constructor;
public class Alba extends Student {
private String company;
public Alba(String name, String school, String company) {
super(name, school);
this.company = company;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
}
package ex02_constructor;
public class AlbaMain {
public static void main(String[] args) {
Alba alba = new Alba("Jessica", "seoul univ", "library");
System.out.println(alba.getName()); // Jessica
System.out.println(alba.getSchool()); // seoul univ
System.out.println(alba.getCompany()); // library
}
}
자동으로 생성자 생성
이해만 하고 코드를 외울 필요는 없다.