is-a 관계가 성립하는 객체간의 관계
슈퍼클래스의 모든 멤버를 서브클래스에서 물려받아 선언 없이 사용
슈퍼클래스 = 부모클래스 = 상위클래스 = 조상클래스
서브클래스 = 자식클래스 = 하위클래스 = 자손클래스
private 접근제한자가 지정된 멤버는 상속 대상에서 제외
생성자는 상속 대상에서 제외
-> 생성자의 이름은 자신의 클래스, 상속받은 생성자는 부모 클래스 이름이므로 규칙에 위반
자바는 단일 상속만 지원
-> 두 개 이상의 슈퍼클래스를 지정할 수 없음
별도로 상속 대상을 지정하지 않을 경우 java.lang.Object
클래스 자동 상속
-> java.lang.Object
: 자바 최상위 클래스
< 상속 기본 문법 >
calss 서브클래스명 extends 슈퍼클래스명 {
}
public static void main(String[] args) {
Child c = new Child(); // 인스턴스 생성
c.num = 5; // 부모클래스로부터 상속받은 num 변수 초기화
c.ParentPrn(); // 상속받아서 사용 가능
c.showNum(); // 5 출력됨
}
class Parent{ // 부모 클래스 생성
int num; // 부모 클래스 멤버 변수 선언
public void ParentPrn() {
System.out.println("슈퍼클래스의 ParentPrn()")
}
}
class Child extends Parent { // 부모 클래스를 상속받는 자식 클래스 생성
public void ChildPrn() {
System.out.println("서브클래스의 ChildPrn()")
}
public void showNum() {
System.out.println("부모클래스로부터 상속받은 num : " + num)
// 부모클래스로부터 num을 상속받았기 때문에 선언하지 않고 그대로 변수 사용 가능
}
}
코드 재사용성 증가
코드 유지보수성 용이해짐
A has a B = A가 B를 포함한다
가장 일반적인 객체간의 관계
특정 클래스 내에서 다른 클래스의 인스턴스를 생성하여 해당 인스턴스를 다루는 관계
ex) 자동차 - 엔진, 스마트폰 - 카메라
class Engine {
int cc = 3000; // 배기량
}
class Car {
String modelName = "그랜져";
Engine engine = new Engine();
// 인스턴스 생성을 통해 접근 가능
public void showInfo() {
System.out.println(modealName);
// 자신의 멤버변수이므로 변수명으로 바로 접근 가능
System.out.println(engine.cc);
// 참조변수를 통해 접근 가능
}
}
A is a B = A는 B이다
특정 클래스가 다른 클래스를 상속받아 해당 클래스의 멤버를 선언없이 다루는 관계
ex) 자동차 - 소방차, 핸드폰 - 스마트폰
class FireEngine extends Car {
// 위의 Car 클래스를 상속받는 소방차 클래스
int supplyLimit = 10000; // 소방차 클래스의 멤버변수
public void showFireEngineInfo() {
System.out.println(supplyLimit);
// 본인의 멤버변수기 때문에 바로 사용 가능
System.out.println(modelName);
// 부모 클래스의 멤버변수 접근 가능
System.out.println(engine.cc);
// 부모와 포함관계인 Engine 객체에도 접근 가능
}
}
생성자: 클래스명과 이름이 같고 리턴타입이 없는 메서드의 일종
생성자는 상속X
-> 상속받을 경우 자신의 클래스명과 생성자명이 다르기 때문에 생성자 정의 규칙 위반
서브 클래스 인스턴스 생성 전 슈퍼클래스 인스턴스 먼저 생성
-> 서브클래스 생성자 호출 시 슈퍼클래스 생성자 먼저 호출하여 슈퍼클래스 인스턴스 생성 후 서브클래스 인스턴스 생성되기 때문!
< Manager 인스턴스를 생성하는 과정 >
슈퍼클래스의 인스턴스가 생성된 후 서브클래스의 인스턴스가 생성됨
new Manager()
코드에 의해 "Manager() 생성자"로 이동
"Manager() 생성자"에 의해 슈퍼클래스 "Employee()" 호출
-> "Manager() 생성자" 내에 자동으로 만들어지는 super()
때문
"Employee() 생성자"에서 "Object()" 호출
-> "Employee() 생성자" 내에 자동으로 만들어지는 super()
때문
Object 인스턴스 생성, "Object() 생성자" 내 코드 실행됨
Employee 인스턴스 생성, "Employee() 생성자" 내 코드 실행
Manager 인스턴스 생성, "Manager() 생성자" 내 코드 실행
⭐ 입력
public static void main(String[] args) {
Manager m = new Manager("홍길동", 3000, "개발팀");
}
class Employee {
String name;
int salary;
public Employee() {
// 기본 생성자 정의
super();
System.out.println("Employee() 생성자 호출됨");
}
}
class Manager extends Employee {
String depart;
public Manager() {
// 기본 생성자 정의
super();
System.out.println("Manager() 생성자 호출됨");
}
public Manager(String name, int salary, String depart) {
// 생성자 오버로딩
System.out.println("Manager(String, int, int) 생성자 호출됨");
this.name = name;
this.salary = salary;
this.depart = depart;
// 부모클래스를 상속받아서 employee 클래스의 멤버변수 사용 가능
}
}
📌 출력
Employee() 생성자 호출됨
Manager(String, int, int) 생성자 호출됨
접근제한자 : 멤버에 대한 접근 범위를 제한하는 키워드
public > protected > default > private
- public : 모든 패키지의 모든 클래스에서 접근 가능
- protected : 같은 패키지거나 다른 패키지의 서브클래스에서 접근 가능
- default : 같은 패키지에서만 접근 가능
- private : 자신의 클래스에서만 접근 가능
⭐ access 패키지의 Parent 클래스
package access;
public class Parent {
public int publicVar;
protected int protectedVar;
int defaultVar; // default 타입은 생략 가능!
private int privateVar;
public void useMember() {
this.publicVar = 10;
this.protectedVar = 20;
this.defaultVar = 30;
this.privateVar = 40;
}
}
⭐ access 패키지의 Same 클래스
package access;
public class Same {
public void useMember() {
Parent p = new Parent();
// 같은 패키지 내의 다른 클래스이기 때문에
// 인스턴스 생성 후 참조변수를 통해 접근!
// has-a 관계!!
// 같은 패키지 내에서는 import 불필요함
p.publicVar = 10;
p.protectedVar = 20;
p.defaultVar = 30;
// 세 개만 접근 가능
}
}
private
로 선언한 변수에는 접근 불가능⭐ other 패키지의 Parent 클래스를 상속 받는 Child 클래스
package other;
import access.Parent;
// 패키지가 다르기 때문에 import 필요!
public class Child extends Child {
// Paren 클래스 상속
// 상속은 인스턴스 생성 필요없음
// 참조변수로 접근하는 게 아니니까!
public void useMember() {
this.publicVar = 10;
this.protectedVar = 20;
// 두 개만 접근 가능
Parent p = new Parent();
// 인스턴스 생성
p.publicVar = 10;
// 하나만 접근 가능
}
}
상속을 받게 되면 is-a 관계이기 때문에 public
과 protected
로 선언한 변수에 접근 가능
하지만 참조변수를 통해 접근하게 되면 상속이 아닌 has-a 관계의 포함관계이기 때문에 protected
는 접근이 불가능해지고 public
만 접근 가능!
⭐ other 패키지의 Parent 클래스를 상속 받지 않는 Not 클래스
package other;
import access.Parent;
// 다른 패키지라서 import 필요!
pulbic class Not {
public void useMember() {
Parent p = new Parent();
p.publicVar = 10;
// 하나만 접근 가능
}
}
public
만 접근 가능!