[Java] 상속과 다형성
자바 클래스를 만들 때, 클래스 간의 관계를 판단해보자.
- is a 관계
- has a 관계
🚗 예1) 자동차 클래스 - 엔진 클래스, 바퀴 클래스 ...
- '자동차 has a 엔진' 관계를 가지고 있다.
: 엔진 클래스를 자동차 클래스의 멤버변수화 시키면 된다.
📱 예2) 휴대폰 클래스 - 아이폰 클래스, 안드로이드폰 클래스 ...
- '아이폰 is a 휴대폰' 이라는 관계를 가지고 있다.
: is a 관계를 가지고 있으면 상속 관계를 만들어서 상속의 이점을 누릴 수 있다.
1. 상속 (Inheritance)
- '물려받는다'는 의미
- B클래스가 A클래스를 상속받으면, B클래스는 A클래스가 가지고 있는 구성원(멤버변수, 메서드) 사용할 수 있음
- ⚡ 자바에서는 모든 클래스가 다른 클래스를 상속받는데, 그 최초의 부모클래스는
Object
클래스이다 ⚡
1) 상속관계의 클래스 생성
- '물려받는다'는 의미
- B클래스가 A클래스를 상속받으면, B클래스는 A클래스가 가지고 있는 구성원(멤버변수, 메서드) 사용할 수 있음
- ⚡ 자바에서는 모든 클래스가 다른 클래스를 상속받는데, 그 최초의 부모클래스는
Object
클래스이다 ⚡
문법:
class B
extends
A
{ ... }
고객 정보를 관리하는 'Customer' 클래스가 있을 때, 이 클래스의 구성요소를 모두 포함하면서 새로운 속성과 기능을 가진 'VIPCustomer' 클래스를 만들어보자.
(1) protected 접근제한자
- 부모클래스의 멤버변수를 private으로 선언하면 자식클래스에서 접근 불가능하다.
- 상속관계의 클래스에서는 접근할 수 있도록 protected를 사용한다.
(접근제한자 - 이전 포스팅 참고)
<Customer.java>
public class Customer {
protected int customerID;
protected String customerName;
protected String customerGrade;
}
<VIPCustomer.java>
public class VIPCustomer extends Customer {
// 자식클래스인 VIPCustomer 클래스만의 멤버변수
double saleRatio;
}
<CustomerTest.java>
public class CustomerTest {
public static void main(String[] args) {
VIPCustomer vc1 = new VIPCustomer();
// VIPCustomer 클래스는 customerName 멤버변수가 없지만,
// Customer 클래스로부터 상속받았기 때문에 사용 가능
vc1.customerName = "홍길동";
System.out.println(vc1.customerName); // 홍길동
}
}
(2) super()
- 부모클래스의 참조값을 가지고 있는 예약어. 자식클래스에서 부모클래스로 접근할 때 사용
- 명시하지 않아도 자식클래스 생성자에서 super()를 자동 호출함
- super()를 호출하면 부모클래스의 디폴트 생성자가 호출됨
= ⚡ 자식클래스의 객체가 만들어질때 무조건 부모클래스 객체가 먼저 만들어짐 ⚡
자식클래스가 부모클래스의 멤버변수와 메서드를 사용할 수 있는 이유!!
부모클래스인 Customer 클래스에 아래와 같이 생성자를 구현했을 때,
public class Customer {
protected int customerID;
protected String customerName;
protected String customerGrade;
// 생성자를 직접 구현 ( => 디폴트 생성자 안만들어짐)
public Customer(int customerID, String customerName) {
this.customerID = customerID;
this.customerName = customerName;
customerGrade = "Silver";
}
}
VIPCustomer.java에서는 오류가 발생한다.
VIPCustomer 클래스의 생성자를 명시하지 않았기 때문에, 컴파일시에 디폴트생성자와 그 안에 super()가 자동 생성된다.
super()가 부모클래스의 디폴트생성자를 호출해야 하는데, Customer클래스에는 디폴트생성자가 없어 오류가 발생하는 것이다.
아래와 같이 VIPCustomer 클래스의 생성자와 super()를 명시해준다.
public class VIPCustomer extends Customer {
double saleRatio;
public VIPCustomer(int customerID, String customerName) {
super(customerID, customerName); // 부모클래스의 생성자 호출
super.customerGrade = "VIP"; // 부모클래스의 멤버변수 참조
saleRatio = 0.1;
}
}
2) 메서드 오버라이딩 (Method Overriding)
- 부모클래스의 메서드를 자식클래스에서 재정의
- 메서드의 반환형, 이름, 매개변수 개수/자료형이 모두 같아야 함
(그렇지 않으면 다른 메서드로 인식됨)
<Customer.java>
public class Customer {
protected int customerID;
protected String customerName;
protected String customerGrade;
public Customer(int customerID, String customerName) {
this.customerID = customerID;
this.customerName = customerName;
customerGrade = "Silver";
}
// 가격을 반환하는 메서드
public double calcPrice(double price) {
return price;
}
// VIP손님은 정가를 반환하지 않을 거라서 재정의 필요
}
<VIPCustomer.java>
public class VIPCustomer extends Customer {
double saleRatio;
public VIPCustomer(int customerID, String customerName) {
super(customerID, customerName);
super.customerGrade = "VIP";
saleRatio = 0.1;
}
// 메소드 오버라이딩
@Override
public double calcPrice(double price) {
return price * (1-saleRatio);
}
// VIPCustomer 클래스에 맞게 재정의해서 사용
}
2. 다형성 (Polymorphism)
- 하나의 코드가 여러 자료형으로 구현되어 실행되는 것을 뜻함
- 필요에 따라 상속받은 모든 클래스를 하나의 상위 클래스로 처리하거나, 다형성에 의해 각 자식클래스의 구현을 실행할 수 있음
1) 묵시적 클래스 형변환
- 자식클래스로 객체를 생성할 때, 그 객체를 참조하는 변수의 자료형을 부모클래스로 형변환하여 사용할 수 있다.
Customer vc = new VIPCustomer();
- 덜 정밀한 자료형 → 더 정밀한 자료형으로의 형변환 = Upcasting
(형변환 - 이전 포스팅 참고)
- VIPCustomer는 Customer클래스가 가지고 있는 구성원들을 모두 가지고 있기 때문이다.
- 선언한 클래스형에 기반하여 멤버변수/메서드에 접근할 수 있다.
public class CustomerTest {
public static void main(String[] args) {
Customer c = new Customer(10, "김철수");
VIPCustomer v = new VIPCustomer(11, "홍길동");
// 묵시적 형변환
Customer vc = new VIPCustomer(12, "알파카");
System.out.println(v.saleRatio); // 0.1
// System.out.println(vc.saleRatio);
// vc는 Customer 클래스를 참조하는 변수이므로, saleRatio 변수에 접근 불가
}
}
2) 가상메서드
변수
와 메서드
가 사용하는 메모리는 다르다.
- 멤버변수 : 인스턴스가 생성될 때마다
스택 메모리
에 생성됨
- 메서드 : 메모리상의
메서드 영역
에 생성됨
(멤버변수처럼 인스턴스가 생성될때마다 새로 생성되지 않음)
- 메서드를 호출하면 메서드 영역의 주소를 참조하여 명령이 실행된다.
public class CustomerTest {
public static void main(String[] args) {
Customer c = new Customer(10, "김철수");
VIPCustomer v = new VIPCustomer(11, "홍길동");
Customer vc = new VIPCustomer(12, "알파카");
System.out.println(c.calcPrice(1000)); // 1000.0
System.out.println(v.calcPrice(1000)); // 900.0
// 가상메서드
System.out.println(vc.calcPrice(1000)); // 900.0
}
}
- ⚡ 선언한 클래스형이 아닌, 생성된 인스턴스의 메서드를 호출한다. ⚡
Author And Source
이 문제에 관하여([Java] 상속과 다형성), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@hmjang28/Java-상속과-다형성
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
- 하나의 코드가 여러 자료형으로 구현되어 실행되는 것을 뜻함
- 필요에 따라 상속받은 모든 클래스를 하나의 상위 클래스로 처리하거나, 다형성에 의해 각 자식클래스의 구현을 실행할 수 있음
Customer vc = new VIPCustomer();
- 덜 정밀한 자료형 → 더 정밀한 자료형으로의 형변환 = Upcasting
(형변환 - 이전 포스팅 참고) - VIPCustomer는 Customer클래스가 가지고 있는 구성원들을 모두 가지고 있기 때문이다.
public class CustomerTest {
public static void main(String[] args) {
Customer c = new Customer(10, "김철수");
VIPCustomer v = new VIPCustomer(11, "홍길동");
// 묵시적 형변환
Customer vc = new VIPCustomer(12, "알파카");
System.out.println(v.saleRatio); // 0.1
// System.out.println(vc.saleRatio);
// vc는 Customer 클래스를 참조하는 변수이므로, saleRatio 변수에 접근 불가
}
}
변수
와 메서드
가 사용하는 메모리는 다르다.- 멤버변수 : 인스턴스가 생성될 때마다
스택 메모리
에 생성됨 - 메서드 : 메모리상의
메서드 영역
에 생성됨
(멤버변수처럼 인스턴스가 생성될때마다 새로 생성되지 않음)
public class CustomerTest {
public static void main(String[] args) {
Customer c = new Customer(10, "김철수");
VIPCustomer v = new VIPCustomer(11, "홍길동");
Customer vc = new VIPCustomer(12, "알파카");
System.out.println(c.calcPrice(1000)); // 1000.0
System.out.println(v.calcPrice(1000)); // 900.0
// 가상메서드
System.out.println(vc.calcPrice(1000)); // 900.0
}
}
Author And Source
이 문제에 관하여([Java] 상속과 다형성), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@hmjang28/Java-상속과-다형성저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)