상속쓰기 전
Desktop Class
package com.kh.chap01_beforeVSafter.before.model.vo;
public class Desktop {
private String brand;
private String pCode;
private String pName;
private int price;
private boolean allInOne;
public Desktop() {
}
public Desktop(String brand, String pCode, String pName, int price, boolean allInOne) {
this.brand = brand;
this.pCode = pCode;
this.pName = pName;
this.price = price;
this.allInOne = allInOne;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getBrand() {
return brand;
}
public void setpCode(String pCode) {
this.pCode = pCode;
}
public String getpCode() {
return pCode;
}
public void setpName(String pName) {
this.pName = pName;
}
public String getpName() {
return pName;
}
public void setPrice(int price) {
this.price = price;
}
public int getPrice() {
return price;
}
public void setAllInOne(boolean allInone) {
this.allInOne = allInone;
}
public boolean isAllInOne() { // 관례적 표현 get대신 is로 표현
return allInOne;
}
public String information() {
return "brand : " + brand + ", pCode : " + pCode + ", pName : " + pName + ", price : " + price + ", allInOne : " + allInOne;
}
}
Smartphone Class
package com.kh.chap01_beforeVSafter.before.model.vo;
public class SmartPhone {
private String brand;
private String pCode;
private String pName;
private int price;
private String mobileAgency;
public SmartPhone() {
}
public SmartPhone(String brand, String pCode, String pName, int price, String mobileAgency) {
this.brand = brand;
this.pCode = pCode;
this.pName = pName;
this.price = price;
this.mobileAgency = mobileAgency;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getpCode() {
return pCode;
}
public void setpCode(String pCode) {
this.pCode = pCode;
}
public String getpName() {
return pName;
}
public void setpName(String pName) {
this.pName = pName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getMobileAgency() {
return mobileAgency;
}
public void setMobileAgency(String mobileAgency) {
this.mobileAgency = mobileAgency;
}
public String information() {
return "brand : " + brand + ", pCode : " + pCode + ", pName : " + pName + ", price : " + price + ", mobileAgency : " + mobileAgency;
}
}
Tv Class
package com.kh.chap01_beforeVSafter.before.model.vo;
public class Tv {
private String brand;
private String pCode;
private String pName;
private int price;
private int inch;
public Tv() {
}
public Tv(String brand, String pCode, String pName, int price, int inch) {
this.brand = brand;
this.pCode = pCode;
this.pName = pName;
this.price = price;
this.inch = inch;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getpCode() {
return pCode;
}
public void setpCode(String pCode) {
this.pCode = pCode;
}
public String getpName() {
return pName;
}
public void setpName(String pName) {
this.pName = pName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getInch() {
return inch;
}
public void setInch(int inch) {
this.inch = inch;
}
public String information() {
return "brand : " + brand + ", pCode : " + pCode + ", pName : " + pName + ", price : " + price + ", inch : " + inch;
}
}
실행 클래스
package com.kh.chap01_beforeVSafter.before.run;
import com.kh.chap01_beforeVSafter.before.model.vo.Desktop;
import com.kh.chap01_beforeVSafter.before.model.vo.SmartPhone;
import com.kh.chap01_beforeVSafter.before.model.vo.Tv;
public class BeforeRun {
public static void main(String[] args) {
// Desktop 객체 생성
// brand, pCode, pName, price, allInOne
Desktop d = new Desktop("삼성", "d-01", "짱짱데스크탑", 200000, true);
// Tv 객체 생성
// brand, pCode, pName, price, inch
Tv t = new Tv("엘지", "T-01", "겁나 얇은 티비", 350000, 65);
// SmartPhone 객체 생성
// brand, pCode, pName, price, mobileAgency
SmartPhone s = new SmartPhone("애플", "s-01", "아이폰", 1300000, "KT");
System.out.println(d.information());
System.out.println(t.information());
System.out.println(s.information());
}
}
컴파일 결과
유지보수 요청 : pName => productName 으로 바꿔라... 제조일자(createDate) 필드 추가해라 ...3개다
세 클래스에 공통적인 필드와 메소드들이 존재함
이런 중복된 코드들을 따로 "부모클래스"로 한번만 정의해두면 중복된 코드들을 주일 수 있음!!
=> 수정과 같은 유지보수 요청이 들어왔을 때 일일히 찾아서 수정할 필요 없이
한번만 정의해둔 부모클래스만 수정하면 전체적으로 반영됨
세 클래스가 공통적으로 가지고 있는 것
=> brand, pCode, pName, price 핋드들, setter/getter, information 메소드
==> product 클래스 미리 정의해볼것!
상속을 쓴다면 ?
Desktop Class
package com.kh.chap01_beforeVSafter.after.model.vo;
//자식 ----------> 부모
//후손 ----------> 조상
//하위 ----------> 상위
//this ----------> super
public class Desktop extends Product {
private boolean allInOne;
public Desktop() {
}
public Desktop(String brand, String pCode, String pName, int price, boolean allInOne) {
// this.brand = brand; // this : 이 클래스의 주소값
// brand ~ price 네 개의 값들은 부모클래스(Product)의 필드에 대입
// 해결방법1. 부모클래스에 있는 필드르 protected 접근 제한자로 수정
/*
super.brand = brand;
super.pCode = pCode;
super.pName = pName;
super.price = price;
*/
// 해결방법2. 부모클래스에 있는 setter 메소드 활용하기 (public 이기 때문에 setter 메소드 사용가능)
/*
super.setBrand(brand);
super.setpCode(pCode);
super.setpName(pName);
super.setPrice(price);
*/
// 해결방법3. 부모 생성자 호출하기 => 우리는 이걸로 간다.
// this 생성자 this(), super 생성자 super() 위치가 항상 위여야한다
super(brand,pCode,pName,price);
this.allInOne = allInOne;
}
public boolean isAllInOne() {
return allInOne;
}
public void setAllInOne(boolean allInOne) {
this.allInOne = allInOne;
}
// 오버라이딩 : 부모클래스에 있는 매소드를 자식 클래스에서 재정의 하는 것
public String information() {
return super.information() + ", allInOne : " + allInOne;
}
}
Smartphone Class
package com.kh.chap01_beforeVSafter.after.model.vo;
public class SmartPhone extends Product{
public String mobileAgency;
public SmartPhone() {
}
public SmartPhone(String brand, String pCode, String pName, int price, String mobileAgency) {
super(brand, pCode, pName, price);
this.mobileAgency = mobileAgency;
}
public String getMobileAgency() {
return mobileAgency;
}
public void setMobileAgency(String mobileAgency) {
this.mobileAgency = mobileAgency;
}
public String information() {
return super.information() + ", mobileAgency : " + mobileAgency;
}
}
Tv Class
package com.kh.chap01_beforeVSafter.after.model.vo;
public class Tv extends Product{
private int inch;
public Tv() {
}
public Tv(String brand, String pCode, String pName, int price, int inch) {
super(brand, pCode, pName, price);
this.inch = inch;
}
public int getInch() {
return inch;
}
public void setInch(int inch) {
this.inch = inch;
}
public String information() {
return super.information() + ", inch : " + inch;
}
}
상속을 쓰기 전에는 없는 Product Class
package com.kh.chap01_beforeVSafter.after.model.vo;
public class Product {
// 세 클래스 모두 공통적으로 가지고 있는 요소들 (필드, 메소드) 만을 기술
private String brand;
private String pCode;
private String pName;
private int price;
public Product() {
}
public Product(String brand, String pCode, String pName, int price) {
this.brand = brand;
this.pCode = pCode;
this.pName = pName;
this.price = price;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getpCode() {
return pCode;
}
public void setpCode(String pCode) {
this.pCode = pCode;
}
public String getpName() {
return pName;
}
public void setpName(String pName) {
this.pName = pName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String information() {
return "brand : " + brand + ", pCode : " + pCode + ", pName : " + pName + ", price : " + price;
}
}
실행 Class
package com.kh.chap01_beforeVSafter.after.run;
import com.kh.chap01_beforeVSafter.after.model.vo.Desktop;
import com.kh.chap01_beforeVSafter.after.model.vo.SmartPhone;
import com.kh.chap01_beforeVSafter.after.model.vo.Tv;
public class AfterRun {
public static void main(String[] args) {
// Desktop 객체 생성
// brand, pCode, pName, price, allInOne
Desktop d = new Desktop("삼성", "d-01", "짱짱데스크탑", 20000, true);
// Tv 객체 생성
// brand, pCode, pName, price, inch
Tv t = new Tv("엘지", "t-01", "겁나 얇은 티비", 350000, 65);
// SmartPhone 객체 생성
// brand, pCode, pName, price, mobileAgency
SmartPhone s = new SmartPhone("애플", "s-01", "아이폰", 1300000, "KT");
System.out.println(d.information());
System.out.println(t.information());
System.out.println(s.information());
s.setPrice(120000000); // 부모클래스에 있는 메소드 호출
s.setMobileAgency("SKT"); // 자식 클래스에 있는 메소드 호출
// System.out.println(s.information()); // 오버라이딩
}
}
컴파일 결과
상속의 장점
- 보다 적은 양의 코드로 새로운 클래스 작성 가능
- 중복된 코드를 별도로 관리하기 때문에 코드의 추가 변경에 용이(프로그램의 생산성과 유지보수에 크게 기여)
상속의 특징
- 자식객체룰 가지고 부모클래스에 있는 메소드를 마치 내 것처럼 호출 가능
- 부모클래스에 있는 메소드를 오버라이딩을 통해 자식 클래스에서 재정의 가능
=> 오버라이딩을 하는 순간 자식클래스에 있는 메소드 우선권을 가짐
클래스간의 상속은 다중상속이 불가능하다 (단일 상속만 가능)
실습예제
Vehicle Class
package com.kh.chap02_inherit.model.vo;
public class Vehicle {
private String name;
private double mileage;
private String kind;
public Vehicle() {
}
public Vehicle(String name, double mileage, String kind) {
this.name = name;
this.mileage = mileage;
this.kind = kind;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getMileage() {
return mileage;
}
public void setMileage(double mileage) {
this.mileage = mileage;
}
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}
public String information() {
return "name : " + name + ", milage : " + mileage + ", kind : " + kind ;
}
public void howToMove() {
System.out.println("움직이다.");
}
}
Car Class
package com.kh.chap02_inherit.model.vo;
public class Car extends Vehicle {
private int tire;
public Car() {
}
public Car(String name, double mileage, String kind, int tire) {
super(name, mileage, kind);
this.tire = tire;
}
public int getTire() {
return tire;
}
public void setTire(int tire) {
this.tire = tire;
}
public String information() {
return super.information() + ", tire : " + tire;
}
@Override // 어노테이션(생략가능) 대신 부모에 무조건 이 메소드 이름이 있어야 함
public void howToMove() { // 이름 이상하게 하면 오류남
System.out.println("바퀴를 굴려 움직인다.");
}
@Override
public String toString() {
return "아무말";
}
}
Ship Class
package com.kh.chap02_inherit.model.vo;
public class Ship extends Vehicle{
private int propeller;
public Ship() {
}
public Ship(String name, double mileage, String kind, int propeller) {
super(name, mileage, kind);
this.propeller = propeller;
}
public int getPropeller() {
return propeller;
}
public void setPropeller(int propeller) {
this.propeller = propeller;
}
public String information() {
return super.information() + ", propeller : " + propeller;
}
@Override
public void howToMove() {
System.out.println("프로펠러를 돌려서 움직인다.");
}
}
Airplane Class
package com.kh.chap02_inherit.model.vo;
public class Airplane extends Vehicle{
public int tire;
public int wing;
public Airplane() {
}
public Airplane(String name, double mileage, String kind, int tire, int wing) {
super(name, mileage, kind);
this.tire = tire;
this.wing = wing;
}
public int getTire() {
return tire;
}
public void setTire(int tire) {
this.tire = tire;
}
public int getWing() {
return wing;
}
public void setWing(int wing) {
this.wing = wing;
}
public String information() {
return super.information() + ", tire : " + tire + ", wing : " + wing;
}
@Override
public void howToMove() {
System.out.println("바퀴를 굴리다가 날개를 휘저으며 움직인다.");
}
}
실행 Class
package com.kh.chap02_inherit.run;
import com.kh.chap02_inherit.model.vo.Airplane;
import com.kh.chap02_inherit.model.vo.Car;
import com.kh.chap02_inherit.model.vo.Ship;
public class InheritRun /*extends Object*/ { // 자바의 모든 클래스는 object의 후손, object에서 있는 메소드를 쓸 수 있음
public static void main(String[] args) {
Car c = new Car("벤틀리", 12.5, "세단", 4);
Ship s = new Ship("낚시배", 3, "어선", 1);
Airplane a = new Airplane("종이비행기", 0.01, "제트기", 10, 4);
System.out.println(c.information());
System.out.println(s.information());
System.out.println(a.information());
c.howToMove(); // 부모클래스에 있는 howToMove 메소드를 사용가능
s.howToMove();
a.howToMove();
System.out.println(c.hashCode());
System.out.println(c.equals(s)); // 그럼 부모가 2명인가요? 다중상속인가요? ㄴㄴ 얘의 부모가 object의 자식 => 즉 할머니 같은 느낌
System.out.println(c.toString()); // Car에서 toString을 오버라이딩 해서 반환값을 바꿔 줄 수 있음
System.out.println(c/*.toString()*/);
}
}
컴파일
정리
상속의 장점
- 보다 적은 양의 코드로 새로운 클래스 작성 가능
- 코드를 공통적을 관리하기 때문에 추가나 변경에 용이 (유지보수, 생산성 up)
상속의 특징
- 클래스간의 상속에 있어서는 다중상속이 안된다!!(단일 상속만 가능 즉, 부모는 하나다)
- 자식객체는 부모클래스에 있는 메소드를 마치 내 것처럼 호출 가능
+ 부모클래스에 있는 메소드가 맘에 안들면 자식 클래스에서 오버라이딩 가능 (내 입맛대로 재정의)
- 부모클래스에 정의돼있는 protected 필드는 자식클래스에서 직접 접근 가능
- 명시되어있지는 않지만 모든 클래스(제공하는 클래스, 직접만든 클래스)는 Object 클래스의 후손이다.
=> 즉, object클래스에 있는 메소드를 마음대로 호출 가능!!
=> 뿐만 아니라 오버라이딩을 통해 재정의도 가능함!!