상속화란?
상속이라는 말 그대로 부모 클래스에 있는 특징(함수, 데이터)들을 자식 클래스가 그대로 물려받는 것이다. 따라서, 상속화를 사용하면 상위 클래스의 데이터와 메서드를 다시 정의하지 않아도 된다.
- 상속화의 장점
- 기존 코드를 재활용 함으로서 재사용성을 증대 → 재사용성이 높아지면 코드의 중복성 제거 && 코드는 덜 복잡해 짐
- 다양한 표현이 가능하다. 추상화를 통해 공통된 부분으로 부모 클래스를 만든 후 이를 활용해 다양한 자식 클래스를 만들어 낼 수 있다.
public class Phone {
String brand; // 필드
String model; // 필드
public Phone(String brand, String model) { // 생성자
this.brand = brand;
this.model = model;
}
public void call(String phoneNumber) {
// 전화 걸기 로직
}
public void sendMessage(String phoneNumber, String message) {
// 문자 보내기 로직
}
public class Camera { // 이너 클래스
public void takePicture() {
// 사진 촬영 로직
}
public void recordVideo() {
// 동영상 촬영 로직
}
}
}
이렇게 Phone 이라는 Class가 있을 때 이 Phone을 상속받아 다양한 개별 속성을 가진 휴대폰을 만들 수 있을 것이다. 이를 다형성이라고 하며 이는 오버로딩(Overloading)과 오버라이딩(Overriding)과도 관련있다.
이로써, 객체 지향형 프로그래밍 언어의 특징(상속, 다형성, 캡슐화, 정보은닉, 추상화)들 또한 모두 다 연관된 개념이라는 것도 알 수 있다!
- 상속화 키워드
class 자식클래스 extends 부모클래스 {
// 내용
}
이전에 썼던 Phone 그대로 예시를 적용해서 내용을 조금 추가 해 보았다.
- 부모 클래스 (Phone)
휴대폰의 공통 기능을 모아 추상화 시켰다.
package Phone;
public class Phone {
String brand; // 필드
String model; // 필드
public Phone(String brand, String model) { // 생성자
this.brand = brand;
this.model = model;
}
public void call(String phoneNumber) {
// 전화 걸기 로직
System.out.println(phoneNumber + "로 전화를 겁니다.");
}
public void sendMessage(String phoneNumber, String message) {
// 문자 보내기 로직
System.out.println(phoneNumber + "로 문자를 보냅니다.");
System.out.println(message);
System.out.println( "💭메세지를 전송합니다.");
}
public class Camera { // 이너 클래스
public void takePicture() {
// 사진 촬영 로직
System.out.println("사진을 촬영합니다.");
}
public void recordVideo() {
// 동영상 촬영 로직
System.out.println("동영상을 촬영합니다.");
}
}
}
- 자식 클래스(Iphone)
휴대폰이 켜질 때 🍏APPLE 이 보이도록 하는 기능과 Applepay 기능 추가
package Phone;
// Phone 클래스를 상속받는 Iphone 클래스
public class Iphone extends Phone {
// Iphone은 Phone 클래스의 생성자를 호출하기 위해 super(brand, model)메서드 사용
public Iphone(String brand, String model) {
super(brand, model);
}
// Iphone을 켤 때 Iphone 클래스에서만 동작
void appleTurnon(String brand, String model){
System.out.println(brand+"휴대폰을 켭니다.");
System.out.println(model+"기종입니다.");
}
// Iphone에서만 동작하는 applePay
void applePay(String brand){
System.out.println(brand+"Pay를 시작합니다.");
}
}
✅ 코드 분석 ✅
super()메서드는 자식 클래스에서 부모 클래스의 생성자를 호출하기 위한 메서드이다.
자식 클래스에서 생성자를 정의할 때, 부모 클래스의 생성자를 호출하지 않으면 부모 클래스의 기본 생성자가 호출되지만 위에 만든 예시처럼 부모 클래스와 동일한 매개변수 (→ brand와 model 같은 매개변수)가 존재할 때 자식 클래스에서 사용하고 싶다면 super()를 사용하여 호출해주어야 한다.
🚨 super()를 사용하여 호출해주지 않았을 때는 아래와 같은 에러가 발생했다.
java: constructor Phone in class Phone.Phone cannot be applied to given types; required: java.lang.String,java.lang.String found: no arguments reason: actual and formal argument lists differ in length
- 실행 클래스 (Main)
package Phone;
public class Main {
public static void main(String[] args) {
// Phone 클래스의 객체 생성
Phone p = new Phone("SAMSUNG", "울트라 23");
// 참조변수 p에서 객체의 동작 호출
p.call("010-1234-5678");
p.sendMessage("010-1234-5678", "안녕하세요");
// 내부 클래스 호출을 위해 객체 생성
Phone.Camera c = p.new Camera();
c.takePicture();
c.recordVideo();
System.out.println();
// Iphone 클래스의 객체 생성
Iphone ip = new Iphone("🍏APLLE", "아이폰 13Pro");
ip.appleTurnon(ip.brand, ip.model);
ip.applePay(ip.brand);
ip.call("010-9876-5432");
ip.sendMessage("010-9876-5432","큰일났어... 레옹이 죽은 것 같아 ");
// 내부 클래스의 호출을 위해 객체 생성
Phone.Camera ic = ip.new Camera();
ic.takePicture();
ic.recordVideo();
}
}
// 출력 결과
// 010-1234-5678로 전화를 겁니다.
// 010-1234-5678로 문자를 보냅니다.
// 안녕하세요
// 💭메세지를 전송합니다.
// 사진을 촬영합니다.
// 동영상을 촬영합니다.
//🍏APLLE휴대폰을 켭니다.
// 아이폰 13Pro기종입니다.
// 🍏APLLEPay를 시작합니다.
// 010-9876-5432로 전화를 겁니다.
// 010-9876-5432로 문자를 보냅니다.
// 큰일났어... 레옹이 죽은 것 같아
// 💭메세지를 전송합니다.
// 사진을 촬영합니다.
// 동영상을 촬영합니다.
✅ 코드 분석 ✅
객체를 생성할 때 객체에 String brand, String model 정보를 받게 했음으로 브랜드와 모델 정보를 함께 전달 해주어야 한다. 이와 마찬가지로 call과 sendMessage 또한 매개변수를 입력 받도록 선언했기 때문에 맞는 값을 전달 해주어야 한다.
→ 만약, 전달하지 않는다면? super()로 값을 전달하지 않았을 때와 동일한 에러가 발생한다.
java: constructor Phone in class Phone.Phone cannot be applied to given types; required: java.lang.String,java.lang.String found: no arguments reason: actual and formal argument lists differ in length
Camera 클래스는 Phone 클래스의 내부 클래스로 선언되어 있기 때문에 외부 클래스인 Phone의 객체를 통해 내부 클래스의 객체 생성 후 메서드를 사용해야 한다. 만약 객체를 생성하지 않고 Camera.Phone; 과 같이 사용한다면 java: not a statement 라는 에러가 발생한다. 멍령문이 아니라는 에러로 수행할 수 없다는 의미이다.
⇒ 예시를 만들어 보며 어제 배운 내부 클래스, 외부 클래스 그리고 생성자를 다시 복습해보는 기회가 되어 의미 있었던 예시 만들기였다. 객체 지향 프로그래밍이 가지는 특성들에 대해서도 하나 씩 이런 게 이런 걸 말하는 거 였구나를 직접 느낄 수 있는 시간이다. 비록 이론 중심으로 공부하고 있지만, 알고리즘 문제를 풀 때에도 단순하게 메소드가 작동하는 것이 아니라는 걸 생각하면 신기하고 또 재미있는 듯 하다.
상속 관계와 포함 관계
상속 관계와 포함 관계는 “A는 B이다.” vs “ A는 B를 가지고 있다.” 를 만들어 봄으로써 쉽게 생각할 수 있다.
class Clothes{
// 참조 변수가 없는 기본 변수 color, type
String color;
String type;
// 생성자 메서드
public Clothes(String color, String type){
this.color = color; // color 필드 초기화
this.type = type; // type 필드 초기
}
}
public class ReferenceExample {
public static void main(String[] args) {
// Clothes 클래스의 인스턴스 생성
// new 키워드를 사용하여 메모리 공간 확보
// ootd는 클래스의 인스턴스를 가리키는 참조변수
Clothes ootd = new Clothes("검은색","후드티");
// 인스턴스의 color와 type 필드 출력
System.out.println("오늘 입을 옷은 "+ ootd.color +" "+ ootd.type+"입니다🧥");
// 인스턴스를 참조하는 참조 변수 ootd 출력
System.out.println(ootd);
}
}
// 결과값
// 오늘 입을 옷은 검은색 후드티입니다🧥
// java_0424.Clothes@13fee20c (참조변수의 위치는 컴퓨터마다 다르게 나올 것)
참조 변수 예시에서 사람을 추가하였다.
⭕ Person은 Clothes를 가지고 있다.
❌ Person은 Clothes이다.
Person은 Clothes를 가지고 있다. 라는 결과로 포함관계임을 알 수 있다.
마찬가지로 앞서 했던 Phone 예시에서
❌ Iphone은 Phone을 가지고 있다.
⭕ Iphone은 Phone 이다.
Iphone은 Phone 이다. 가 자연스러움으로 상속관계이다.
상속과 포함관계까지 알아봤다. 이제 다형성의 메서드 오버라이딩과 예시에서 봤던 super키워드와 super() 메서드도 정리 해야지! 뭔가 예시를 작성해보면서도 생각을 했는데 계속 관련된 것들이 나온다는 것이 신기하기도 하고 끝없는 내가 모르는 게 또 얼마나 많을까 생각도 든다.
재미있다. 그래도 배워가는 게 하나 씩 늘어나고 확실히 배워가는 것 같아서 너무 좋다.
자습을 하는데도 불구하고 정말 열심히 할 수 밖에 없는 환경을 만들어 주는 것이 코스의 장점인 듯 하다!
'LANGUAGE > JAVA' 카테고리의 다른 글
[JAVA] 객체 지향 프로그래밍의 속성 / 캡슐화(Encaptulation) (0) | 2023.04.25 |
---|---|
[JAVA] JAVA 객체지향 프로그래밍 / 메서드 오버라이딩(Method Overriding)이란? (0) | 2023.04.25 |
[JAVA] 기본 변수 와 참조 변수 / 하루 종일 걸려 이해한 참조 변수 쉽게 이해하기 위해 정리 (0) | 2023.04.25 |
[JAVA] System.arraycopy 배열에 값 추가하기 / 배열 복사 메서드 (0) | 2023.04.24 |
[JAVA] JAVA 객체지향 프로그래밍 / 메서드 오버로딩(Method Overloading)이란? (0) | 2023.04.23 |