Day 14(21.09.23) - Gomserker/Java-101 GitHub Wiki

21. 상속(Inheritance)

(1) μƒμ†μ΄λž€?

객체 μ§€ν–₯ ν”„λ‘œκ·Έλž˜λ°μ—μ„œμ˜ μƒμ†μ΄λž€ κ°œλ…μ€ λΆ€λͺ¨ 클래슀의 멀버(field, method)λ₯Ό μžμ‹ ν΄λž˜μŠ€μ—κ²Œ λ¬Όλ €μ£ΌλŠ” 것을 λœ»ν•œλ‹€.
μ’€ 더 μ΄ν•΄ν•˜κΈ° μ‰½κ²Œ μ–˜κΈ°ν•˜λ©΄, μžλ™μ°¨ μ‹œμž₯μ—λŠ” ν¬λ“œ, 페라리, λ²€μΈ  λ“± λ‹€μ–‘ν•œ 메이컀가 있고 메이컀에 따라 μ„±λŠ₯κ³Ό μ™Έν˜•μ€ μ²œμ°¨λ§Œλ³„μ΄λ‹€. ν•˜μ§€λ§Œ, κ²°κ΅­ μžλ™μ°¨λΌλŠ” 큰 집합에 μ†Œμ†λ˜μ–΄ 있으며, μžλ™μ°¨λΌλŠ” 큰 κ°œλ…μ΄ κ°€μ§€λŠ” 곡톡적인 속성은 λͺ¨λ“  μžλ™μ°¨ 메이컀가 κ³΅ν†΅μ μœΌλ‘œ κ°€μ§€κ³  μžˆλ‹€. μ—¬κΈ°μ„œ μžλ™μ°¨λΌλŠ” λ”μš± 포괄적인 κ°œλ…μ„ λΆ€λͺ¨ 클래슀, 그리고 각 μžλ™μ°¨ 메이컀λ₯Ό μžμ‹ 클래슀라고 μƒκ°ν•˜λ©΄ μ’‹λ‹€. μ΄λŸ¬ν•œ 상속은 잘 개발된 클래슀λ₯Ό μž¬μ‚¬μš©ν•˜μ—¬ μƒˆλ‘œμš΄ 클래슀λ₯Ό λ§Œλ“œλŠ” κ²ƒμ΄λ―€λ‘œ μ½”λ“œμ˜ 쀑볡을 쀄여주고, λ”μš± 효율적인 κ°œλ°œμ„ κ°€λŠ₯ν•˜κ²Œ ν•œλ‹€.

(2) 클래슀 상속

ν•˜μ§€λ§Œ 객체 μ§€ν–₯ ν”„λ‘œκ·Έλž˜λ°μ—μ„œμ˜ 상속은 ν˜„μ‹€κ³ΌλŠ” 달리 μžμ‹ ν΄λž˜μŠ€κ°€ λΆ€λͺ¨ 클래슀λ₯Ό 선택할 수 μžˆλ‹€. μžλ°”μ—μ„œλŠ” 이럴 λ•Œ extendsλΌλŠ” ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•œλ‹€. 예λ₯Ό λ“€μ–΄, Porsche의 경우 μžλ™μ°¨ λ©”μ΄μ»€λ‘œ 유λͺ…ν•˜μ§€λ§Œ ν•œλ•Œ 탱크와 같은 것듀도 λ§Œλ“€μ—ˆλ˜ λΈŒλžœλ“œμ΄λ‹€. ν•˜μ§€λ§Œ μžλ™μ°¨λ₯Ό λ§Œλ“€κ³  μ‹Άλ‹€ ν• λ•ŒλŠ” μžλ™μ°¨ 곡μž₯을 μ„Έμš°λŠ” κ²ƒμ²˜λŸΌ, 이 κ²½μš°μ—” Tank ν΄λž˜μŠ€κ°€ μ•„λ‹Œ Car 클래슀λ₯Ό μƒμ†ν•˜λŠ” 것이닀.

class Porsche extends Car {
   //Field
   //Constructor
   //Method
}

μœ„ μ˜ˆμ‹œμ²˜λŸΌ PorcheλŠ” extends ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•΄ Car 클래슀λ₯Ό μƒμ†ν•˜κ² λ‹€κ³  μ„ μ–Έν•˜λŠ” 것이닀. ν•˜μ§€λ§Œ, ν•˜λ‚˜μ˜ μžλ™μ°¨ 곡μž₯μ—μ„œ νƒ±ν¬λ‚˜ λΉ„ν–‰κΈ°λ₯Ό 뽑아낼 μˆ˜λŠ” 없듯이(μ‹€μ œλ‘œλŠ” κ°€λŠ₯ν• μˆ˜λ„ μžˆλ‹€κ³  쳐도) μžλ°” μ—μ„œλŠ” 닀쀑 상속을 ν—ˆμš©ν•˜μ§€ μ•Šκ³  μžˆλ‹€. 즉, extends ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•΄μ„œ Car 클래슀λ₯Ό μƒμ†ν•˜κ² λ‹€κ³  μ„ μ–Έν–ˆλ”°λ©΄ Tank, Airplaneκ³Ό 같은 λΆ€λͺ¨ 클래슀λ₯Ό μ€‘λ³΅μœΌλ‘œ κ°€μ§ˆ 수 μ—†λ‹€. μ•„λž˜λŠ” 클래슀 μƒμ†μ˜ μ˜ˆμ‹œμ΄λ‹€.

//Porche.java
public class Porsche {
 public static void main(String[] args) {
   
   Vehicle normalCar = new Vehicle();
   SportsCar carrera = new SportsCar();

   normalCar.maxSpeed = 120;
   normalCar.name = "Just car";
   normalCar.info();

   carrera.maxSpeed = 300;
   carrera.name = "Carrera";
   carrera.cost = 12000;

   carrera.info();
 }
}
//Vehicle.java
public class Vehicle {
 int maxSpeed;
 String name;

 public void info() {
   System.out.println("이름: " + name);
   System.out.println("μ΅œλŒ€ 속도: " + maxSpeed);
  }
}
//SportsCar.java
public class SportsCar extends Vehicle{
	int cost;
}

Result

이름 : Just car
μ΅œλŒ€ 속도 : 120
이름 : Carrera
μ΅œλŒ€ 속도 : 300

μœ„ μ˜ˆμ‹œμ—μ„œ 확인할 수 μžˆλ“―μ΄ SportsCar ν΄λž˜μŠ€λŠ” λΆ€λͺ¨ 클래슀인 Vehicle의 λͺ¨λ“  ν•„λ“œμ™€ μƒμ„±μžλ₯Ό μ΄μ–΄λ°›μ•˜κΈ° λ•Œλ¬Έμ— Porsche ν΄λž˜μŠ€μ—μ„œ nameκ³Ό maxSpeed의 ν•„λ“œκ°’μ„ μ„€μ •ν•  수 있고, info() λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•΄μ„œ 정보λ₯Ό λΆˆλŸ¬μ˜€κΈ°κΉŒμ§€ ν•  수 μžˆλ‹€λŠ” 것을 ν™•μΈν–ˆλ‹€. ν•˜μ§€λ§Œ μ—¬κΈ°μ„œ λ¬Έμ œκ°€ μžˆλ‹€. λΆ„λͺ… SportsCar ν΄λž˜μŠ€μ—μ„œλŠ” costλΌλŠ” ν•„λ“œκ°’μ„ ν•˜λ‚˜ μΆ”κ°€ν–ˆλŠ”λ° info() λ©”μ†Œλ“œμ— ν•΄λ‹Ή λ‚΄μš©μ΄ λ°˜μ˜λ˜μ§€ μ•Šμ•˜λ‹€. 이 뢀뢄은 λ©”μ†Œλ“œ μž¬μ •μ˜(Method Override)λ₯Ό ν†΅ν•΄μ„œ ν•΄κ²°ν•  수 μžˆλ‹€.

(3) λ©”μ†Œλ“œ μž¬μ •μ˜(Method Override)

λ©”μ†Œλ“œ μž¬μ •μ˜λž€ λΆ€λͺ¨ 클래슀의 λ©”μ†Œλ“œκ°€ μžμ‹ ν΄λž˜μŠ€μ— 맞게 μ„€κ³„λ˜μ–΄ μžˆμ§€ μ•Šμ•„ μžμ‹ ν΄λž˜μŠ€μ—μ„œ μ‚¬μš©ν•˜κΈ° μ–΄λ €μšΈ 경우, 문자 κ·ΈλŒ€λ‘œ λΆ€λͺ¨ 클래슀의 λ©”μ†Œλ“œλ₯Ό 'μž¬μ •μ˜(override)'ν•¨μœΌλ‘œμ„œ λΆ€λͺ¨ 클래슀의 λ©”μ†Œλ“œλ₯Ό μžμ‹ 클래슀의 상황에 맞게 μ‚¬μš©ν•  수 μžˆκ²Œλœλ‹€. μ—¬κΈ°μ„œ λ©”μ†Œλ“œλ₯Ό μž¬μ •μ˜ ν•˜κΈ° μœ„ν•΄μ„  '@Override'λΌλŠ” μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•΄μ•Όν•˜λŠ”λ°, μ˜ˆμ‹œλŠ” μ•„λž˜μ™€ κ°™λ‹€.

//SportsCar.java
public class SportsCar extends Vehicle{
	int cost;
	
	@Override //Vehicle 클래슀λ₯Ό 상속받은 SportsCarμ—μ„œ λΆ€λͺ¨ 클래슀의 info() λ©”μ†Œλ“œλ₯Ό μž¬μ •μ˜ν•΄μ„œ μ‚¬μš©ν•˜κ² λ‹€κ³  μ„ μ–Έ
	public void info() {
		System.out.println("가격: " + cost);
	}
}

Result

이름: Just car
μ΅œλŒ€ 속도: 120
가격: 12000

SportsCar ν΄λž˜μŠ€μ—μ„œ μž¬μ •μ˜(μ˜€λ²„λΌμ΄λ”©)ν•œ info() λ©”μ†Œλ“œκ°€ μ œλŒ€λ‘œ 적용된 것을 확인할 수 μžˆλ‹€. ν•˜μ§€λ§Œ 또 λ‹€μ‹œ λ¬Έμ œκ°€ λ°œμƒν–ˆλ‹€. SportsCar의 ν•„λ“œκ°’μΈ 이름과 μ΅œλŒ€ 속도가 보이질 μ•Šκ²Œ 됐닀. μ—¬κΈ°μ„œ λ©”μ†Œλ“œ μž¬μ •μ˜μ˜ νŠΉμ§•μ„ 확인할 수 μžˆλŠ”λ°, μžμ‹ ν΄λž˜μŠ€μ—μ„œ λ©”μ†Œλ“œλ₯Ό μž¬μ •μ˜ ν•˜κ³ , μžμ‹ 객체(μ—¬κΈ°μ„  SportsCar)μ—μ„œ λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ λΆ€λͺ¨ λ©”μ†Œλ“œ(μ—¬κΈ°μ„  Vehicle)κ°€ ν˜ΈμΆœλ˜μ§€ μ•Šκ³  μžμ‹ 클래슀의 info() λ©”μ†Œλ“œλ§Œ ν˜ΈμΆœλ˜λŠ” 것을 μ•Œ 수 μžˆλ‹€. μ΄λ ‡κ²Œ λΆ€λͺ¨ 클래슀의 λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•΄μ•Όν•˜λŠ” 상황이 λ°œμƒν•  κ²½μš°μ—”, ν•˜λ‚˜ν•˜λ‚˜ 좜λ ₯ μ½”λ“œλ₯Ό μƒˆλ‘œ μž‘μ„±ν• μˆ˜λ„ μžˆκ² μ§€λ§Œ λΆ€λͺ¨ 클래슀의 λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•΄μ„œ μ‚¬μš©ν•œλ‹€λ©΄ 훨씬 효율적으둜 μž‘μ—…μ„ μ§„ν–‰ν•  수 μžˆκ²Œλœλ‹€.

(4) super

μœ„ ν•­λͺ©μ—μ„œ μ„€λͺ…ν–ˆλ“―, μžμ‹ ν΄λž˜μŠ€μ—μ„œ λΆ€λͺ¨ 클래슀의 λ©”μ†Œλ“œλ₯Ό μž¬μ •μ˜ ν–ˆκ³ , μžμ‹ κ°μ²΄μ—μ„œ μž¬μ •μ˜ν•œ λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•  κ²½μš°μ—” λΆ€λͺ¨ 클래슀의 λ©”μ†Œλ“œλŠ” 호좜이 λ˜μ§€ μ•ŠλŠ”λ‹€. λΆ€λͺ¨ 클래슀의 λ©”μ†Œλ“œκ°€ ν•„μš”κ°€ 없을땐 λ¬Έμ œκ°€ λ˜μ§€ μ•Šμ§€λ§Œ, μœ„ μ˜ˆμ‹œμ™€ 같이 λΆ€λͺ¨ 클래슀의 λ©”μ†Œλ“œκ°€ μ£ΌλŠ” 정보(이름과 μ΅œλŒ€μ†λ„)κ°€ ν•„μš”ν•œ κ²½μš°μ—λŠ” λΆ€λͺ¨ 클래슀의 λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•΄μ•Ό ν•˜λŠ”λ°, μ΄λŸ΄λ•Œ μ‚¬μš©ν•˜λŠ” 것이 super ν‚€μ›Œλ“œμ΄λ‹€. superλ₯Ό λͺ…μ‹œμ μœΌλ‘œ μ‚¬μš©ν•΄ λΆ€λͺ¨ 클래슀의 μƒμ„±μžμ™€ λ©”μ†Œλ“œ 등을 ν˜ΈμΆœν•  수 μžˆλ‹€.(이 νŽ˜μ΄μ§€μ—μ„œλŠ” λ©”μ†Œλ“œλ§Œ ν˜ΈμΆœν•œλ‹€.) μ‚¬μš©λ²•μ€ μ•„λž˜μ™€ κ°™λ‹€.

//SportsCar.java
public class SportsCar extends Vehicle{
	int cost;
	
	@Override //Vehicle 클래슀λ₯Ό 상속받은 SportsCarμ—μ„œ λΆ€λͺ¨ 클래슀의 info() λ©”μ†Œλ“œλ₯Ό μž¬μ •μ˜ν•΄μ„œ μ‚¬μš©ν•˜κ² λ‹€κ³  μ„ μ–Έ
	public void info() {
                super.info(); //superν‚€μ›Œλ“œλ‘œ λΆ€λͺ¨ 클래슀λ₯Ό ν˜ΈμΆœν•œ λ‹€μŒμ— λ‹· μ—°μ‚°μž(.)둜 infoλ©”μ†Œλ“œλ₯Ό 호좜
		System.out.println("가격: " + cost);
	}
}

Result

이름: κ·Έλƒ₯ μ°¨
μ΅œλŒ€ 속도: 120
이름: Carrera
μ΅œλŒ€ 속도: 300
가격: 12000

super ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•œ λ‹€μŒμ— λΆ€λͺ¨ 클래슀의 info λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•œ κ²°κ³Ό μ˜λ„ν–ˆλ˜ λŒ€λ‘œ 이름과 μ΅œλŒ€ 속도, 그리고 가격이 좜λ ₯된 것을 확인할 수 μžˆλ‹€.