코드스테이츠_국비교육/[Section1]

13_객체지향 프로그래밍 심화(상속)_22.09.06

생각없이 해도 생각보다 좋다. 2022. 9. 6. 10:52

학습 키워드

  • 상위 클래스, 하위 클래스, 상속 관계의 이해
  • extends 키워드
  • 포함관계
  • 메서드 오버라이딩
  • super 와 super()
  • Object 클래스

 

상속

>의미

: 연관된 일련의 클래스들에 대해 공통적인 규약을 정의하기 위한 문법 요소.

: 다른 기존의 클래스의 모든 멤버를 사용하며, 추가적으로 확장시킬 때 사용하는 문법 요소

>상속관계 구분

  • 상위 클래스

: 하위 클래스를 상속하는 클래스

: 하위 클래스로 확장되는 클래스

  • 하위 클래스

: 상위 클래스를 상속받는 클래스

: 상위 클래스를 확장하는 클래스

>상속의 특징과 장점

: 상위 클래스의 멤버를 상속받기 때문에 코드의 중복을 줄일 수 있다.

: 다형적 표현이 가능하다.

//다형적 표현 : 하나의 객체가 여러 모양으로 표현되는 것.

//예시: A가 B에 속한 범주일 때, A는 A이기도 하고, A는 B이기도 하다.

>단일 상속

: 자바에선 다중 상속은 허용되지 않음.

: 인터페이스가 있기 때문에.

>상위 클래스 참조형과 하위 클래스 인스턴스

: 참조 변수의 다형성.

: 상위 클래스 참조형으로 하위 클래스의 인스턴스를 만들 수 있다.

: 가능한 이유는 하위 클래스의 인스턴스 멤버의 수가 같거나 더 많기 때문이다.

: 이같은 경우 상위 클래스 참조형 배열을 만들어 하위 클래스 인스턴스를 요소로 두는 배열을 만들어 관리할 수 있다.

//중요: 상속 관계 내용 중에서 실 사용에 있어 중요해 보인다. 나중에 정리할 때 포인트를 두자.

>상속의 코드 구조

public class Main {
    public static void main(String[] args) {
        Person p1 = new Person();
        Programmer p2 = new Programmer();
        Runner p3 = new Runner();
        JavaProgrammer p4 = new JavaProgrammer();
        //아래와 같이 인스턴스를 생성할 수도 있음.
        Person p5 = new Person();
        Person p6 = new Programmer();
        Person p7 = new Runner();
        Person p8 = new JavaProgrammer();
        //이 경우, 사용의 제한이 존재함.
        //참조형의 클래스가 갖는 멤버만 사용가능.
        //예외
        //: 메서드 오버라이딩이 된 경우, 하위 클래스 멤버도 사용 가능.
        /*
        p2.coding(); // 코드 짠다
        p6.coding(); // 에러
        */
        //응용
        Person[] people = new Person[3];
        people[0] = new Programmer();
        people[1] = new Runner();
        people[2] = new JavaProgrammer();
        //메서드 오버라이딩만 잘 해두면 배열로 한방에 사용 가능.
    }
}

class Person {
    int age;
    void sleep(){
        System.out.println("잔다");
    }
}

class Programmer extends Person{
    int codingLevel;
    void coding(){
        System.out.println("코드 짠다");
    }
}

class Runner extends Person{
    int runningLevel;
    void running(){
        System.out.println("달린다");
    }
}

class JavaProgrammer extends Programmer{
    int javaLevel;
    void oop(){
        System.out.println("객체!지향!");
    }
}

 

 

메서드 오버라이딩, Method Overriding

>의미

: 상위 클래스로부터 상속받은 메서드와 동일한 이름의 메서드를 재정의하는 것.

: 상위 클래스의 메서드를 하위 클래스에서 같은 이름의 메소드로 덮어쓰는 것.

//상속 관계가 확장시킨다는 의미를 보여주는 예시라고 생각한다.

>특징 및 장점

: 클래스의 메소드들을 확장시킬 수 있다.

: 다형적 표현을 할 수 있다.

>조건

1. 메서드명, 매개변수, 반환타입이 완전히 일치해야 한다.

2. 접근 제어자의 범위가 상위 클래스의 메서드와 같거나 넓어야 한다.

3. 상위 클래스의 메서드보다 많이 선언할 수 없다.

>코드 예시

public class Main {
    public static void main(String[] args) {
        Cake c1 = new Cake();
        CheeseCake c2 = new CheeseCake();
        Cake c3 = new CheeseCake();
        c1.taste(); //음~달아
        c2.taste(); //음~꾸덕해
        c3.taste(); //음~꾸덕해
        //c3. taste();
        //참조형이 Cake 이기 때문에 CheeseCake 인스턴스를 생성했더라도,
        //원래는 Cake 의 멤버에만 접근 가능
        //하지만 taste() 메소드는 오버라이딩 되었기에 
    }
}

class Cake{
    void taste(){
        System.out.println("음~달아");
    }
}

class CheeseCake extends Cake{
    void taste(){
        System.out.println("음~꾸덕해");
    }
    //super.taste();
    //오버라이딩된 상위 클래스의 메소드는 super키워드로 불러올 수 있음.
}

 

super 키워드와 super() 메서드

>개요

: this 키워드와 this() 메서드와 개념적으로 유사함.

: this는 자신의 객체에 대한 참조변수, this() 메서드는 자신의 생성자 호출.

: super은 상위 클래스의 객체에 대한 참조변수, super() 메서드는 상위 클래스의 생성자를 호출.

>상속 관계 내에서 구분

  • this: 현재 this가 사용된 클래스
  • super: 현재 super가 사용된 클래스의 상위 클래스
  • this(): 현재 this()가 사용된 클래스의 생성자 호출
  • super(): 현재 super()가 사용된 클래스의 상위 클래스 생성자 호출

>super() 주의 사항

: this()와 마찬가지로 생성자 안에서만 사용되며, 반드시 첫 줄에 와야한다!

: 생성자 내에 super()가 없다면 컴파일러가 자동 생성한다.

//자동 생성 super()주의

//자동으로 생성되는 super()은 인자가 없기 때문에 상위 클래스 내에 매개변수가 없는 생성자가 있어야 한다.

 

Object 클래스

>의미

: 자바의 최상위 클래스

: 모든 클래스의 상위 클래스

: 모든 클래스는 Object의 확장판

: 모든 클래스는 Objec의 규칙을 포함함.

>자동 생성(컴파일러)

: 클래스를 생성하면 자동으로 컴파일러가 extends Object를 추가함.

>Object 메서드

toString();

: 객체 정보를 문자열로 출력

equals(Object obj);

: 인자로 주어진 스택 메모리값과 비교하여 boolean 값을 반환함. 

hashCode();

: Hashtable 또는 HashMap에서 동일 객체여부 판단에 사용하며 int 값을 반환.(객체의 위치정보와 관련됨)

wait();

: 현재 쓰레드 일시정지(void)

notify();

: 일시정지된 쓰레드 재동작(void)

//우리가 코드를 작성하면서 toString();등을 아무 작업을 안해도 쓸 수 있는 이유!

 

포함

>의미

: 클래스의 멤버로 다른 클래스 타입의 참조변수를 선언하는 것.

>포함 관계의 사용

: 사실상 상속보다는 포함 관계를 다룰 일이 더 많음.

>상속과 포함의 사용 기준

1. 상속: IS-A관계(~is a~); '~은 ~이다.'

2. 포함: HAS-A관계(~has a~); '~은 ~을 가지고 있다.'

: 위 두 관계 중 어디에 속하는지 보고 상속과 포함 중 무엇을 사용할 지 판단하면 된다.

//구분 기준에 큰 의미가 있을까?

//근데 그냥 사실 코드짜면서 그냥 적당히 가져다 쓸거면 포함 관계를 사용하고, 같은 규칙을 주고 이용할거면 상속을 쓰

지 않을까?

>코드 예시

public class Main {
    public static void main(String[] args) {
        // User 에 대한 인스턴스를 미리 만들어야 사용 가능
        User userLOL = new User("Rabbit", "jungle");
        User userStar = new User("Larva", "zerg");
        // User 의 참조값을 이용한 포함 관계 사용 예시
        Game g1 = new Game("LOL", userLOL);
        Game g2 = new Game("Star", userStar);
        g1.showInfo(); //g1, g2는 Game의 멤버에만 접근 가능
        g2.showInfo(); //Game에서 User에 접근 가능
        /*
        game: LOL
        id: Rabbit
        mainType: jungle
        game: Star
        id: Larva
        mainType: zerg
        */

    }
}

class Game{
    String name;
    User userinfo;
    Game(String name, User userinfo){
        this.name = name;
        this.userinfo = userinfo;
    }
    void showInfo(){
        System.out.printf("game: %s\n", name);
        System.out.printf("id: %s\n", userinfo.id); //User의 참조값을 받아 이용하는 모습
        System.out.printf("mainType: %s\n", userinfo.mainType);
    }
}

class User{
    String id, mainType;
    User(String id, String mainType){
        this.id = id;
        this.mainType = mainType;
    }
}