01. 상속의 개념
02. 클래스 상속과 객체
03. 상속과 접근 지정자
04. 상속과 생성자
# 상속
º 상속
- 상위 클래스의 특성(필드, 메소드)을 하위 클래스에 물려주는 것
- 슈퍼 클래스
→ 특성을 물려주는 상위 클래스
- 서브 클래스
→ 특성을 물려 받는 하위 클래스
→ 슈퍼 클래스에 자신만의 특성(필드, 메소드)을 추가
→ 슈퍼 클래스의 특성(메소드)을 수정 : 오버라이딩(overriding)
º 상속을 하는 이유는?
- 동일한 특성을 재정의하지 않고 서브 클래스를 정의할 수 있음
# 클래스 상속과 객체
º 상속 선언
public class Person {
}
public class Student extends Person {
}
public class StudentWorker extends Student {
}
º 자바 상속의 특징
- 다중 상속을 지원하지 않는다.
- 상속의 횟수에 제한을 두지 않는다.
- 계층구조의 최상위에 있는 클래스는 java.lang.Object 클래스이다.
# 상속의 장점
- 클래스 사이의 멤버 중복 선언 불필요 → 클래스의 간결화
- 클래스들의 계층적 분류로 클래스 관리 용이
- 클래스(필드, 메소드) 재사용과 확장을 통한 소프트웨어의 생산성 향상
# 자바 클래스 계층 구조
- 모든 클래스는 java.lang.Object 클래스를 자동으로 상속받는다.
(예제1) Point 클래스
public class Point {
private int x, y; //한 점을 구성하는 x, y좌표
public void set(int x, int y) {
this.x = x;
this.y = y;
}
public void showPoint() { //점의 좌표 출력
System.out.println("(" + x + "," + y + ")");
}
}
public class PointEx {
public static void main(String[] args) {
Point p = new Point();
p.set(10, 20);
p.showPoint();
}
}
실행 결과 : (10, 20)
(상속 예제1) Point 클래스 -> ColorPoint 클래스
public class ColorPoint extends Point {
private String color; //점의 색
public void setColor(String color) {
this.color = color;
}
public void showColorPoint() {
System.out.print(color); //점의 색 출력
showPoint(); //Point 클래스에서 정의된 showPoint() 호출
}
}
public class PointEx2 {
public static void main(String[] args) {
Point p = new Point();
p.set(10, 20);
p.showPoint();
ColorPoint cp = new ColorPoint();
cp.set(3, 4); //좌표 지정
cp.setColor("red"); //색 지정
cp.showColorPoint(); //점 출력
}
}
실행 결과
(10, 20)
red(3, 4)
(예제2) TwoDShape (2차원 도형) 클래스
public class TwoDShape {
public double width;
public double height;
public void showDim() {
System.out.println("Width and height are " + width + " and " + height);
}
}
public class Shapes {
public static void main(String[] args) {
TwoDShape shape = new TwoDShape();
shape.width = 10;
shape.height = 20;
shape.showDim();
}
}
실행 결과 : Width and height are 10.0 and 20.0
(상속 예제2) TwoDShape 클래스 -> Triangle 클래스
public class Triangle extends TwoDShape {
public String style;
public double area() {
return width * height / 2;
}
public void showStyle() {
System.out.println("Triangle is " + style);
}
}
public class Shapes {
public static void main(String[] args) {
Triangle t1 = new Triangle();
Triangle t2 = new Triangle();
t1.width = 4.0;
t1.height = 4.0;
t1.style = "isosceles";
t2.width = 8.0;
t2.height = 12.0;
t2.style = "right";
System.out.println("Info for t1:");
t1.showStyle();
t1.showDim();
System.out.println("Area is " + t1.area());
System.out.println();
System.out.println("Info for t2:");
t2.showStyle();
t2.showDim();
System.out.println("Area is " + t2.area());
}
}
실행 결과
Info for t1:
Triangle is isosceles
Width and height are 4.0 and 4.0
Area is 8.0
Info for t2:
Triangle is right
Width and height are 8.0 and 12.0
Area is 48.0
(상속 예제3) TwoDShape 클래스 -> Rectangle 클래스
public class Rectangle extends TwoDShape {
public boolean isSquare() {
if(width == height) return true;
return false;
}
public double area() {
return width * height;
}
}
# 서브 클래스의 객체와 멤버
- 서브 클래스의 객체는 슈퍼 클래스의 멤버도 포함
- 슈퍼 클래스의 private 멤버는 상속되지 않음
→ 서브 클래스에서 직접 접근 불가
→ 슈퍼 클래스의 메소드를 통해서만 접근 가능 (getter/setter 메소드 이용)
- 서브 클래스 객체에 슈퍼 클래스 멤버가 포함되므로 슈퍼 클래스 멤버의 접근은 서브 클래스 멤버 접근과 동일
# 상속과 접근 지정자
º 자바의 접근 지정자
- public, protected, default, private
(상속 관계에서 주의할 접근 지정자는 private와 protected)
º private 멤버
- 슈퍼 클래스의 private 멤버는 서브 클래스를 포함한 다른 모든 클래스에서 접근할 수 없다.
º protected 멤버
- 같은 패키지 내의 모든 클래스에서 접근할 수 있다.
- 동일 패키지 여부와 상관 없이 서브 클래스에서 슈퍼 클래스의 멤버에 접근할 수 있다.
# 슈퍼 클래스 멤버의 접근 지정자
default | private | protected | public | |
같은 패키지의 클래스 | O | X | O | O |
같은 패키지의 서브 클래스 |
O | X | O | O |
다른 패키지의 클래스 | X | X | X | O |
다른 패키지의 서브 클래스 |
X | X | O | O |
(참고) 패키지를 사용하려면
- 프로젝트를 생성하고, class를 정의하기 전에 패키지를 만든다. 만들어 놓은 패키지 속에 class 들을 만들면 된다.
- 패키지 속에 클래스를 생성하면, 패키지명이 자동 생성된다.
- 패키지 밖의 클래스를 상속할 때는 어떤 패키지의 어떤 클래스를 상속하는가를 import 문을 통해 써 주어야 한다.
package PackageB;
import PackageA.A; // 클래스 A가 있는 곳 명시
public class B extends A{
void set() {
i = 1; // default 멤버, 오류
pro = 2;
pri = 3; // private 멤버, 오류
pub = 4;
}
}
- 클래스 B는 클래스 A를 상속받기 때문에 import PackageA.A를 써 주어야 하지만, ABDemo2 에서는 클래스 A의 이름을 언급하지 않으므로 그렇게 할 필요가 없다.
package PackageB;
public class ABDemo2 {
public static void main(String[] args) {
B b = new B();
b.set();
}
}
# 슈퍼 클래스와 서브 클래스의 생성자 간의 호출 및 실행 관계
- 서브 클래스의 생성자가 먼저 호출되지만, 계속하여 슈퍼 클래스의 생성자를 호출하고, 최상위 슈퍼 클래스의 생성자가 실행되면서 아래로 최하위 서브 클래스의 생성자가 실행되는 과정을 거침.
# case1 : 슈퍼클래스(기본생성자), 서브클래스(기본생성자)
- 서브 클래스의 생성자가 기본생성자인 경우 컴파일러는 자동으로 슈퍼클래스의 기본생성자와 짝을 맺는다.
- 생성자가 이미 정의되어 있는 경우, 기본 생성자는 자동 생성되지 않는다.
class A {
public A() { // 기본 생성자
System.out.println(" 생성자 A");
}
public A(int x) { // 매개 변수가 한 개인 생성자
// ....
}
}
class B extends A {
public B() { // 기본 생성자
System.out.println("생성자 B");
}
}
public class ConstructorEx2 {
public static void main(String args[]) {
B b;
b = new B();
}
}
실행 결과
생성자 A
생성자 B
# case3 : 서브클래스에 매개변수가 있는 생성자는 슈퍼클래스의 기본생성자와 짝을 이룸
class A {
public A() { // 기본 생성자
System.out.println("생성자 A");
}
public A(int x) { // 매개 변수가 한 개인 생성자
System.out.println("매개변수 생성자 A");
}
}
class B extends A {
public B() { // 기본 생성자
System.out.println("생성자 B");
}
public B(int x) { // 매개 변수가 한 개인 생성자
System.out.println("매개변수 생성자 B");
}
}
public class ConstructorEx2 {
public static void main(String args[]) {
B b;
b = new B(5);
}
}
실행 결과
생성자 A
매개변수 생성자 B
# super()
- 서브 클래스에서 명시적으로 슈퍼 클래스의 생성자를 선택 호출할 때 사용
- 사용 방식
→ super(parameter);
→ 인자를 이용하여 슈퍼 클래스의 적당한 생성자 호출
→ 반드시 서브 클래스 생성자 코드의 제일 첫 라인에 와야 한다.
'JAVA > 자바 이론' 카테고리의 다른 글
Java | 6 패키지 (0) | 2021.06.06 |
---|---|
Java | 5-2 상속과 다형성 (0) | 2021.05.25 |
Java | 4-3 클래스와 객체 (0) | 2021.04.15 |
Java | 4-2 클래스와 객체 (0) | 2021.04.14 |
Java | 4-1 클래스와 객체 (0) | 2021.04.14 |