JAVA_상속 (Inheritance)

JW__1.7·2022년 7월 28일
1

JAVA 공부일지

목록 보기
14/30

상속 (Inheritance)

  • 어떤 클래스의 필드와 메소드를 다른 클래스가 물려 받아 사용하는 것
  • 부모클래스가 자식클래스에게 필드와 메소드를 물려 준다.
  • 자바에서는 부모클래스를 "슈퍼클래스(super)", 자식클래스를 "서브클래스(sub)"

상속의 장점

  • 동일한 메소드를 클래스마다 여러 번 정의할 필요가 없다.
  • 클래스를 계층(부모-자식) 관계로 관리할 수 있다.
  • 클래스의 재사용과 확장이 쉽다.
  • 새로운 클래스의 작성 속도가 빠르다.

상속 구조

상속 관계의 클래스

  • extends 키워드를 이용해서 상속 관계를 나타낸다.
    자식클래스 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() { }
}

서브클래스

  • 후손들은 끝없이 상속 받아서 사용
  • 상속 판단할 때 "extends" 대신에 "is-a"를 넣어 판단할 수 있다.

학생 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 생성가 호출된다.

부모클래스의 생성자 선택

  • 서브클래스의 생성자는 부모클래스의 생성자를 super( )를 이용해서 호출
  • 부모클래스의 디폴트 생성자를 호출하는 경우 super( ) 생략 가능

부모클래스의 디폴트 생성자를 호출하는 경우

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
	}
}

자동으로 생성자 생성



이해만 하고 코드를 외울 필요는 없다.

0개의 댓글