[Java] 상속

2024. 1. 21. 23:14공부 중/Java

1. 상속

 

가. 객체지향 언어의 특징

특성 내용
추상화 현실의 객체를 추상화 해서 클래스를 구성한다.
다형성 하나의 객체를 여러 가지 타입으로 참조할 수 있다.
상속 부모 클래스의 자산을 물려받아 자식을 정의함으로 코드의 재사용이 가능하다.
캡슐화 데이터를 외부에 직접 노출시키지 않고 메서드를 이용해 보호할 수 있다.

 


나. 상속

 

  • Inheritance
  • 상위 클래스의 멤버를 하위 클래스에서 재사용하기 위함.
  • 유지보수성 향상
  • extends 키워드 사용.
  • 부모의 생성자와 private 제한자가 붙은 경우는 상속되지 않음.
public class Person {
    String name;

    void eat() {
        System.out.println("냠냠");
    }
    void jump() {
        System.out.println("폴짝");
    }
}
public class SpiderMan extends Person {
    boolean isSpider;

    void fireWeb() {
            System.out.println("어떻게?");
    }
}
public class SpiderTest {

    public static void main(String[] args) {
        SpiderMan sman = new SpiderMan();
        sman.isSpider = true;
        sman.fireWeb();
        sman.jump();
    }
}

 


다. Object 클래스

 

모든 클래스의 공통 조상.

 

별도의 클래스를 상속받지 않는다면 extends Object를 생략됨.

 

모든 클래스에는 Object 클래스에 정의된 메서드가 있음.

 

  • java.lang.Object
    • registerNative(): void
    • getClass(): java.lang.Class<?>
    • clone(): java.lang.Object
    • finalize() void
    • (): void
    • 대부분 클래스에서 재정의하는 것
      • hashCode(): int
      • equals(Obj: java.lang.Object): boolean
      • toString(): java.lang.String
    • 멀티 스레드에서 사용하는 것
      • notify(): void
      • notifyAll(): void
      • wait(timeout: long): void
      • wait(timeout: long, nanos int): void
      • wait(): void

 

 

코딩교육 티씨피스쿨

4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등

tcpschool.com

 


라. 다양한 상속 관계

 

가. 단일 상속

 

자바에서는 단일 상속만 지원.

 

대신 interface포함 관계로 한계를 극복한다.

 


나. 포함 관계

 

상속 이외에 클래스를 재활용하는 방법.

 

2개 이상의 클래스에서 특성을 가져올 때 하나는 상속, 나머지는 멤버 변수로 처리.

 

public class Spider {
    void jump() {
        System.out.println("깡총거미는 어마어마한 점프!!");
    }
    void fireWeb() {
        System.out.println("슉슉~~");
    }
}

Spider라는 클래스를 생성한다.

 

public class SpiderMan extends Person {
    boolean isSpider;
    // has a 관계 (포함관계)
    Spider spider;

    public SpiderMan() {
        this.spider = new Spider();
    }

    void fireWeb() {
        if(isSpider) {
            spider.fireWeb();
        }else {
            System.out.println("지금은 안됨");
        }
    }
}

SpiderManspider를 가지고 있으므로 spider를 활용할 수 있다.

 


2. 메서드 재정의

 

가. 오버라이딩

  • Overriding
  • 조상 클래스에 정의된 메서드를 자식 클래스에 적합하게 덮어쓰는 것.
  • 조건
    • 메서드 이름이 같아야 한다.
    • 매개 변수의 개수, 타입, 순서가 같아야 한다.
    • 리턴 타입은 같아야 한다.
    • 접근 제한자는 부모 보다 범위가 넓거나 같아야 한다.
    • 조상보다 더 큰 예외를 던질 수 없다.

 

public class SpiderMan extends Person {
    boolean isSpider;
    // has a 관계 (포함관계)
    Spider spider;

    public SpiderMan() {
        this.spider = new Spider();
    }

    void fireWeb() {
        if(isSpider) {
            spider.fireWeb();
        }else {
            System.out.println("지금은 안됨");
        }
    }
    void jump() {
        if(isSpider) {
            spider.jump();
        } else {
            System.out.println("두 다리로 힘껏 점프");
        }
    }
}

jump()를 재정의했다.

 

1) 이런 경우는?

public class Person {
    private int age;
    private String name;

    void m1() {    }
}
public class SubPerson extends Person {
    //@Override
    void m1(int a) { }
}

결과는?

 

에러가 발생하지도 않고 오버라이딩도 아니다.

 

자식 클래스에서 추가된 메서드로 인식하기 때문이다.

 

@Override를 사용해서 이런 실수를 방지할 수 있다.

 

@Override를 활성화하면 해당 메서드는 반드시 부모의 메서드를 올바르게 재정의해야 한다.

 

그렇지 않으면 오류가 발생한다.

 


나. super

 

1) super.

public class SpiderMan extends Person {
    boolean isSpider;
    // has a 관계 (포함관계)
    Spider spider;

    public SpiderMan() {
        this.spider = new Spider();
    }

    void fireWeb() {
        if(isSpider) {
            spider.fireWeb();
        }else {
            System.out.println("지금은 안됨");
        }
    }
    void jump() {
        if(isSpider) {
            spider.jump();
        } else {
            super.jump() // 변경
        }
    }
}
  • super.jump() : 조상 클래스(Person)의 멤버에 접근하는 방법.
class Parent {
    String x = "parent";
}

class Child extends Parent{
    String x = "child";

    void method(){
        String x = "method";
        System.out.println("x : " + x); // x : method
        System.out.println("this.x : " + this.x); // this.x : child
        System.out.println("super.x : " + super.x); // supder.x : parent
    }
}
/*
x : method
this.x : child
supder.x : parent
*/

사용된 위치에서 범위를 확장해 가며 처음 만난 선언부에 연결됨.

(method 내부 → 해당 클래스 멤버 변수 → 조상 클래스 멤버 변수)

 

2) super()

  • 조상 클래스의 생성자 호출
  • 자식 클래스 생성자의 맨 첫 줄에서만 호출 가능
  • 명시적으로 this() 또는 super()가 호출되지 않는 경우 컴파일러가 super() 자동으로 삽입.
  • 결과적으로 가장 상위의 Object까지 객체가 만들어진다.
  • super()this()는 같이 사용할 수 없다.
public Person(String name) {
    super();
    this.name = name;
}

상위 생성자를 수정하면 하위 클래스의 생성자도 영향을 받는다.

public SpiderMan(){
    this("Peter Parker");
}

public SpiderMan(String name) {
    super(name);
    this.spider = new Spider();
}

 

결과적으로 가장 상위의 Object까지 객체가 만들어진다.

 


다. Annotation

 

컴파일러, JVM, 프레임워크 등이 보는 주석.

 

소스코드에 메타 데이터를 삽입.

 

  • @Deprecated : 컴파일러에게 해당 메서드가 권장되지 않음을 알려줌.
  • @Override : 컴파일러에게 해당 메서드가 override한 메서드임을 알려줌.
  • @SuppressWarnings : 컴파일러에게 사소한 warning의 경우 무시하라 알려줌.
@Override
void jumps() {
    if(isSpider) {
        spider.jump();
    } else {
        super.jump();
    }
}

@Override가 붙어있지 않았다면 새로운 메서드를 생성하는 것으로 컴파일러는 해석했을 것.

 

하지만 @Override 붙어있다면 컴파일러는 개발자가 실수한 것을 알아차리고 알려준다.

 


3. Package & import

 

가. Package

물리적으로 패키지는 클래스 파일을 담고 있는 디렉터리다.

 

많은 클래스를 의미 있는 경로로 계층적으로 관리.

 

모든 클래스는 반드시 하나의 패키지 안에 포함되어야 한다.

(생략 시 default package에 속하게 되지만 권장하지 않음.)

 

com.company.project.service

  • com.company : 회사의 identity
  • project : 프로젝트이름
  • service : 용도

 


나. import

 

다른 클래스를 사용하고 싶을 때.

import java.util.*;

사용해도 성능에 문제가 없음!

 

java.util.List list = new java.util.ArrayList();

동일한 이름을 사용하는 다른 클래스의 경우 import한 package의 이름을 입력한다.

 

java.lang.*;

default import package로 개발자가 추가하지 않아도 컴파일러가 자동으로 추가한다.

 


다. static import

 

int ret = Math.max(a,b);

Math.max()는 static method다.

 

import static java.lang.Math.max;
//또는 import static java.lang.Math.*;
int ret = max(a,b);

static import 방식으로 max()로 줄여 사용할 수 있다.

 

import static java.lang.System.*;
...
//System.out.println(data);
out.println(data);

Sytem.out.println()out.println()으로 줄일 수 있다.

 

참고만 하자.

 


4. 제한자

 

가. 제한자

 

  • modifier
    • 접근 제한자 : public, protected, package, private
    • 그 외 제한자 : static, final, abstract, synchronized
  • 순서는 무관하나 일반적으로 접근 제한자를 가장 앞에 배치한다.

 


나. final

 

더 이상 바뀔 수 없음.

 

1) 용도

  • final class : 더 이상 상속할 수 없음
  • final method : 더 이상 재정의 할 수 없음
  • final variable : 더 이상 값을 바꿀 수 없음

 

2) Blank final

자바는 Blank final을 지원한다.

값이 할당되지 않은 멤버 변수에 대하여 생성자에서 1회 초기화할 수 있다.

 

3) static final

static final : 모든 곳에서 공유되는 유일한 상수.

 


다. 접근 제한자

 

Access modifier.

 

부모의 제한자 범위와 같거나 넓은 범위로만 사용 가능.

 

웬만하면 private 사용하기.

 


'공부 중 > Java' 카테고리의 다른 글

[Java] 인터페이스  (0) 2024.01.22
[Java] 다형성  (0) 2024.01.22
[Java] 객체지향  (0) 2024.01.21
[Java] 배열  (0) 2024.01.21
[Java] 조건문, 반복문  (0) 2024.01.21