안녕하세요, 코린이의 코딩 학습기 채니 입니다.
개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.
super 키워드와 super() 메소드에 대해 알아보기 전, 상속을 하는 이유에 대해서 먼저 짚어보겠습니다.
데스크탑, 스마트폰, tv에 대한 정보를 갖고 있는 VO class를 만들어보았습니다.
Desktop class
public class Desktop {
private String brand;
private String productCode;
private String productName;
private int price;
private String os;
private String monitor;
private String keyboard;
private String mouse;
public Desktop() {}
public Desktop(String brand, String productCode, String productName, int price, String os, String monitor,
String keyBoard, String mouse) {
this.brand = brand;
this.productCode = productCode;
this.productName = productName;
this.price = price;
this.os = os;
this.monitor = monitor;
this.keyboard = keyBoard;
this.mouse = mouse;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getOs() {
return os;
}
public void setOs(String os) {
this.os = os;
}
public String getMonitor() {
return monitor;
}
public void setMonitor(String monitor) {
this.monitor = monitor;
}
public String getKeyBoard() {
return keyboard;
}
public void setKeyBoard(String keyBoard) {
this.keyboard = keyBoard;
}
public String getMouse() {
return mouse;
}
public void setMouse(String mouse) {
this.mouse = mouse;
}
public String getDesktopInfo() {
return "Desktop [" + brand + ", " + productCode + ", " + productName + ", " + price + ", "
+ os + ", " + monitor + ", " + keyboard + ", " + mouse + "]";
}
}
SmartPhone class
public class SmartPhone {
private String brand;
private String productCode;
private String productName;
private int price;
private String os;
private String carrier; //통신사 정보
public SmartPhone() {}
public SmartPhone(String brand, String productCode, String productName, int price, String os, String carrier) {
this.brand = brand;
this.productCode = productCode;
this.productName = productName;
this.price = price;
this.os = os;
this.carrier = carrier;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getOs() {
return os;
}
public void setOs(String os) {
this.os = os;
}
public String getCarrier() {
return carrier;
}
public void setCarrier(String carrier) {
this.carrier = carrier;
}
public String getSmartPhoneInfo() {
return "SmartPhone [" + brand + ", " + productCode + ", " + productName + ", " + price + ", "
+ os + ", " + carrier + "]";
}
}
Tv class
public class Tv {
private String brand;
private String productCode;
private String productName;
private int price;
private String resolution; //화질
private int size;
public Tv() {}
public Tv(String brand, String productCode, String productName, int price, String resolution, int size) {
this.brand = brand;
this.productCode = productCode;
this.productName = productName;
this.price = price;
this.resolution = resolution;
this.size = size;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getResolution() {
return resolution;
}
public void setResolution(String resolution) {
this.resolution = resolution;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public String getTvInfo() {
return "Tv [" + brand + ", " + productCode + ", " + productName + ", " + price + ", "
+ resolution + ", " + size + "]";
}
}
ProductMain class
public class ProductMain {
public static void main(String[] args) {
Desktop desktop = new Desktop("삼성", "samsung-1234", "삼성점보데스크탑", 1_000_000, "Windows11", "좋은모니터", "좋은키보드", "좋은마우스");
SmartPhone smartPhone = new SmartPhone("아이폰", "iphone-11-pro", "아이폰11프로", 800_000, "애플", "SKT");
Tv tv = new Tv("LG", "lg-9898", "울트라와이드샤프TV", 5_000_000, "UHD", 80);
System.out.println(desktop.getDesktopInfo());
System.out.println(smartPhone.getSmartPhoneInfo());
System.out.println(tv.getTvInfo());
}
}
@콘솔출력값
Desktop [삼성, samsung-1234, 삼성점보데스크탑, 1000000, Windows11, 좋은모니터, 좋은키보드, 좋은마우스]
SmartPhone [아이폰, iphone-11-pro, 아이폰11프로, 800000, 애플, SKT]
Tv [LG, lg-9898, 울트라와이드샤프TV, 5000000, UHD, 80]
위 코드들을 보면 정말 거슬리는 한 가지가 있습니다.
바로 중복인데요, Desktop/SmartPhone/Tv class 모두 공통적인 필드를 갖고 있어 계속하여 중복이 발생하였습니다.
이럴 때 중복되는 코드들을 하나의 class에 정의하여 상속한다면, 코드의 중복이 없어지겠죠?
부모 클래스가 될 Product class를 생성해보겠습니다.
public class Product {
private String brand;
private String productCode;
private String productName;
private int price;
public Product() {}
public Product(String brand, String productCode, String productName, int price) {
super();
this.brand = brand;
this.productCode = productCode;
this.productName = productName;
this.price = price;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getProductInfo() {
return brand + ", " + productCode + ", " + productName + ", " + price;
}
}
공통된 코드들을 Product class로 만들고, Desktop/SmartPhone/Tv 클래스가 상속 받게 하였습니다.
자식 클래스인 Desktop 클래스를 대표적인 예로 확인해보겠습니다.
public class Desktop extends Product {
private String os;
private String monitor;
private String keyboard;
private String mouse;
public Desktop() {}
public Desktop(String brand, String productCode, String productName, int price, String os, String monitor,
String keyBoard, String mouse) {
this.brand = brand;
this.productCode = productCode;
this.productName = productName;
this.price = price;
this.os = os;
this.monitor = monitor;
this.keyboard = keyBoard;
this.mouse = mouse;
}
public String getOs() {
return os;
}
public void setOs(String os) {
this.os = os;
}
public String getMonitor() {
return monitor;
}
public void setMonitor(String monitor) {
this.monitor = monitor;
}
public String getKeyBoard() {
return keyboard;
}
public void setKeyBoard(String keyBoard) {
this.keyboard = keyBoard;
}
public String getMouse() {
return mouse;
}
public void setMouse(String mouse) {
this.mouse = mouse;
}
public String getDesktopInfo() {
return "Desktop [" + brand + ", " + productCode + ", " + productName + ", " + price + ", "
+ os + ", " + monitor + ", " + keyboard + ", " + mouse + "]";
}
}
extends 키워드를 이용하여 Product 클래스를 상속 받게 하였습니다만,
생성자와 메소드 등의 brand, productCode, productName, price는 private 접근 제어자이므로 상속은 받았지만 직접 접근이 불가한 상황으로 에러가 발생하였습니다.
이 때, 부모 클래스의 brand, productCode, productName, price를 가져와서 사용하려면 어떻게 해야할까요?
☞ super() 메소드
- 부모 클래스의 생성자 호출
- 생성자의 내부에서만 사용 가능하며 반드시 첫 줄에 단 한 번만 사용
public Desktop(String brand, String productCode, String productName, int price, String os,
String monitor,String keyBoard, String mouse) {
super(brand, productCode, productName, price);
this.os = os;
this.monitor = monitor;
this.keyboard = keyBoard;
this.mouse = mouse;
}
super() 메소드를 이용해 부모 클래스의 생성자를 호출하여 필드 값에 넘어온 매개인자를 대입할 수 있었습니다.
그렇다면 기본 생성자는 어떻게 될까?
public Desktop() {
//super(); 생략
}
언뜻 보기엔, 아무것도 입력이 안되어있는 것 같아보이지만 super()가 생략이 되어있는 상태입니다.
모든 생성자는 첫 줄에 반드시 this() 또는 super()가 있어야합니다. 만일 아무것도 써주지 않으면 JVM은 super()를 자동 삽입합니다.
즉 생성자를 호출할 때 반드시 부모 클래스의 생성자가 호출이 된다는 뜻이고,
이러한 이유로 인하여 자식 생성자로 객체를 생성할 때 부모 클래스의 객체가 만들어지는 것입니다.
☞ super. 키워드
- 부모의 객체를 가리키는 것
- 필드명의 중복 또는 메서드 오버라이딩으로 가려진 부모의 필드 또는 메소드를 호출하기 위해 사용
public String getDesktopInfo() {
return "Desktop [" + super.getProductInfo() + ", "
+ os + ", " + monitor + ", " + keyboard + ", " + mouse + "]";
}
사실 getDesktopInfo()는 오버라이딩이 된 메소드가 아니기도 하고, 애초에 부모클래스의 getProductInfo()가 public 메소드이기 때문에 this. 으로도 접근이 가능합니다.
그렇다면 만일 각 클래스 별 Info 메소드가 아닌 Object가 제공하는 toString 메소드를 오버라이딩해서 사용하고 있다면 어떻게 될까요?
//부모 클래스 Product
public class Product {
private String brand;
private String productCode;
private String productName;
private int price;
public Product() {}
public Product(String brand, String productCode, String productName, int price) {
this.brand = brand;
this.productCode = productCode;
this.productName = productName;
this.price = price;
}
//get,set 생략
@Override
public String toString() {
return brand + ", " + productCode + ", " + productName + ", " + price;
}
public String getProductInfo() {
return brand + ", " + productCode + ", " + productName + ", " + price;
}
}
//자식 클래스 Desktop
public class Desktop extends Product {
private String os;
private String monitor;
private String keyboard;
private String mouse;
public Desktop() {
super();
}
public Desktop(String brand, String productCode, String productName, int price, String os, String monitor,
String keyBoard, String mouse) {
super(brand, productCode, productName, price);
this.os = os;
this.monitor = monitor;
this.keyboard = keyBoard;
this.mouse = mouse;
}
//get,set 생략
@Override
public String toString() {
return "Desktop [" + super.toString() + ", "
+ os + ", " + monitor + ", " + keyboard + ", " + mouse + "]";
}
public String getDesktopInfo() {
return "Desktop [" + super.getProductInfo() + ", "
+ os + ", " + monitor + ", " + keyboard + ", " + mouse + "]";
}
}
public class ProductMain {
public static void main(String[] args) {
Desktop desktop = new Desktop("삼성", "samsung-1234", "삼성점보데스크탑", 1_000_000,
"Windows11", "좋은모니터", "좋은키보드", "좋은마우스");
System.out.println(desktop.toString());
}
}
이렇게 오버라이딩된 메소드를 사용할 때, 그리고 부모 클래스의 메소드를 가져와야할 때는 반드시 super. 키워드를 사용해야 합니다.
만일 자식 클래스의 toString 메소드에서 super. 이 아닌 this. 을 하게 된다면 계속해서 자신의 메소드를 불러오는 것이기 때문에 StackOverFlow에러가 발생하게 됩니다.
이렇게 중복 제거와 super키워드와 super() 메소드를 통해 부모의 생성자, 부모의 메소드에 접근할 수 있었습니다.
☞ protecte 접근제한자
만일 super키워드, super()메소드를 사용하기 싫다! 나는 부모 필드에 직접 접근하고 싶다! 라고 한다면,
부모의 필드는 protected로 지정하면 되겠죠?
protected 접근 제한자 : 동일 패키지의 모든 클래스 + 다른 패키지의 자식 클래스에서 사용 가능
//부모 클래스 Product
public class Product {
protected String brand;
protected String productCode;
protected String productName;
protected int price;
//... 이하 생략
}
//자식 클래스 Desktop
public class Desktop extends Product {
//... 이하 생략
public Desktop(String brand, String productCode, String productName, int price, String os, String monitor,
String keyBoard, String mouse) {
// super(brand, productCode, productName, price);
this.brand = brand;
this.productCode = productCode;
this.productName = productName;
this.price = price;
this.os = os;
this.monitor = monitor;
this.keyboard = keyBoard;
this.mouse = mouse;
}
public String getDesktopInfo() {
return "Desktop [" + brand + ", " + productCode + ", " + productName + ", " + price + ", "
+ os + ", " + monitor + ", " + keyboard + ", " + mouse + "]";
}
}
//Main 메소드
public class ProductMain {
public static void main(String[] args) {
Desktop desktop = new Desktop("삼성", "samsung-1234", "삼성점보데스크탑", 1_000_000, "Windows11", "좋은모니터", "좋은키보드", "좋은마우스");
System.out.println(desktop.getDesktopInfo());
}
}
@콘솔출력값
Desktop [삼성, samsung-1234, 삼성점보데스크탑, 1000000, Windows11, 좋은모니터, 좋은키보드, 좋은마우스]
이렇게 부모 필드의 직접 접근하여 값 대입을 하였고, 직접 접근이 가능하므로 get메소드를 통해 필드 값을 가져오는 게 아닌 직접 필드를 호출하여 메소드 출력을 할 수 있었습니다.
'Java > Java' 카테고리의 다른 글
객체 지향 3대 원칙) 다형성에 대하여, 업 캐스팅, 다운 캐스팅 (0) | 2022.03.24 |
---|---|
상속) is-a-상속관계, has-a-포함관계, 강집합, 약집합 (0) | 2022.03.22 |
상속) 메소드 오버라이딩 (0) | 2022.03.21 |
상속) 최상위 클래스 Object, toString(), equals(Object obj), hashCode(), clone() (0) | 2022.03.21 |
상속) 상속의 특징, 생성자 상속 여부 (0) | 2022.03.21 |