[멋사 TIL] 13기 day6

이은서·2024년 12월 9일
0

멋사

목록 보기
2/11
post-thumbnail

🤔 "중복된 코드를 계속 둬야 할까?"
🤷🏻‍♀️ "어떻게 해결할 수 있을까?"

중복되는 코드가 많을 때 수정해야 할 파트가 많아지기 때문에 오류 발생 확률이 높아진다. 그래서 코드를 불러다 쓰는 방법이 없을까 하고 고민해야 함


🧒🏻 "이모이모! 방이 뭐야?"
👩🏻 "어.. 은 말이야... "

방을 설명하고 나면
안방은 인데~ 엄마 아빠가 자는 이야.
공부방은 인데~ 공부하는 이야.
하고 설명하기 가능


👩🏻‍💻👩🏻‍💻👩🏻‍💻
( 코딩중... )

👩🏻 "버스" "스포츠카" "트럭"의 일반화된 개념이 뭐지?
👩🏻 ... 겠군!! 그러니 의 속성을 상속받는 것으로 구현하자~


➡️ 프로그래밍하다 보면 이런 순서로 가기도 함!



상속을 이용해보자!


⬇️

상속

  • OO는 OO다.
  • OO는 OO의 종류 중 하나다.

라고 표현할 수 있을 때.
a.k.a.  is a 관계 kind of 관계


편할 것 같다고 해서 무조건 상속받아서는 안된다.

말이 되는지를 봐야한다.
한번 상속받게 한 뒤에는 수정하는 게 쉽지가 않음

상속할 때 조심해야 하는 이유.jpg

스택인데 벡터를 상속받는 것부터 잘못됐다...
벡터가 가지는 기능을 다 쓸 수 있다는 뜻이기 때문
중간에서 꺼내는 동작이 일어나기 때문에 잘못 구현된 것!

필드로 선언해서 사용하는 게 나을 뻔했다.
근데도 고칠 수 없다.. 이미 오픈되어 어디선가 사용중일 것...

속성으로 가지면 되지 무작정 상속하면 안된다.
"상속이라는 문법을 사용해야 하나?" 에 대해 고민할 때 "OO는 OO의 종류 중 하나다."에 들어맞는지 체크해보아야




상속을 대하는 자세

문법보다도(별 게 없음), "왜 상속을 해야 하지?"하고 개념을 이해하는 것이 중요



상속을 활용한 개념들

생성자

✏️child가 생성될 때 부모의 생성자가 먼저 실행되고 그 다음에 child의 생성자가 실행된다.
부모의 특정 생성자를 상속받고 싶을 때 오류 발생 가능

✏️ 생성자가 다른 생성자를 호출하게 할 수 있다. 바로

this()

  • this는 인스턴스가 있을 때만 가리킬 수 있다.
  • this()는 생성자만 가리킬 수 있음; 생성자를 의미
  • 내 생성자 중에 같은 일을 하고 있는 애를 호출

this()를 활용하는 것: 순서를 바꿔서도 가능!



cf.   default 생성자를 안 만드는 eu?
아무 값 없이 생성하는 것이 의미가 없는 객체들은 default 생성자를 안 만드는 것이다.

Scanner 객체는 default 생성자가 없다.
➡️ 값을 어디서 줄 거야라는 정보를 주지 않으면 의미가 없기 때문에 정의해주지 않은 것

Scanner 클래스의 생성자 목록.jpg

↳ 위 문서에서 알 수 있는 것: System.in=InputStream




쓰레드

수행 흐름
여지껏은, 기본적으로 단일 쓰레드
카톡 구현하는 경우,
nextInt()는 값 입력할 때까지 기다리고 입력이 들어와야 다음 줄 실행하는데
채팅은 내가 입력을 하면서도 다른 사람이 입력 가능 : 시간을 굉장히 작은 단위로 쪼개서 - 사람이 느끼기에는 동시에 하는 것처럼 느껴지도록 : 멀티 스레드 : 시간 쪼개기
= 타임 쉐어링
스레드 객체 구현되어 있기 때문에 상속받아서 사용하면 됨




상속에 대해 배우보자.

상속의 속성 활용하기


부모 → 자식 ⭕
자식 ← 부모 ❌

Car car2 = new Bus();

부모자식
CarBus
큰 그릇작은 그릇
  • 자식타입으로 부모를 가리키면 좀 이상할 수 있다.
  • 형변환에서 큰 그릇에는 작은 그릇에 담겨있던 걸 담을 수 있었던 걸 떠올리자.
  • 단 이 객체 간의 "형변환"은 상속 관계 내에서만 가능(다른 객체 타입인데 형변환을 해줄 수는 없다.)
  • 부모: 물려준 거까지만 알기 때문에 자식 타입으로 형변환을 시켜줘야 사용 가능 - 명시적 형변환 필요

이원준꺼 다시 한번 보기.. 왜 형질이 더 많은데 더 작은 범위일까? 이해가 되는데 또 안됨



자바는 단일 상속 ⭕, 다중 상속❌

자바는 다중 상속을 허용하지 않는다.
c라는 자식이 a라는 부모와 b라는 부모 동시에게 상속받을 수 없는 것
(파이썬은 순서롤 지정해주는 mro를 통해 가능)

자바는 부모가 하나만 있는 단일 상속
다만 부모의 부모의 부모는 가능!
직계는 가능!
가능한 이유: 자바가 가진 원칙(나중)



자식은 부모가 생기고 나서 생긴다.

child가 생길 때 반드시 parent가 생긴 후에 생긴다
child꺼로 getI()를 하면 자기껄 씀(내 꺼가 없을 때만 부모 꺼 씀)
parent입장에서는 물려준 거밖에 안 보인다.
가리킬 수는 있지만!



Car car2 = new Bus();

레퍼런스 변수 car2와 Car객체
car2는 Car 타입의 참조 변수이다. 즉, "Car 타입으로 보이는 객체를 참조할 수 있다"는 것을 의미한다. 따라서 car2는 Car의 필드와 메서드만 사용할 수 있도록 제한된다.

↳ 실제로 메모리에 저장된 객체는 Bus 전체이지만, 참조 변수는 이를 Car 관점에서만 보게 된다.
car2는 Bus 객체의 일부분만 참조하는 것이 아니라 객체 전체를 참조하고 있지만 접근범위만 Car의 범위까지로 제한될 뿐이다.

일어나는 과정

좌변우변
Car car2new Bus()
car2는 Car 타입의 참조 변수; "Car 타입으로 보이는 객체를 참조할 수 있다"Car의 필드와 메서드를 포함한 Bus 전체 객체가 생성됨

car2에 ⤺ 생성된 Bus 객체의 주소가 저장
car2는 Car 타입의 참조 변수이기 때문에, Car 클래스에 정의된 필드와 메서드만 접근 가능
⁕ 실제 객체는 Bus지만 car2를 통해서는 Car의 기능만 사용할 수 있다.

메모리에서는 무슨 일이 일어날까?
new Bus()호출 → 메모리에 Bus 객체가 생성

이 객체에는:

  • Car의 필드(name, speed)와 메서드가 먼저 메모리에 올라가고
  • 그 후에 Bus 클래스에 추가된 필드와 메서드가 메모리에 올라간다.
package day06;
//자바는 다중상속을 허용하지 않는다.

class Car {
    String name;
    int speed;

    public void 운행하다(){
        System.out.println("차가달립니다.");
    }
}

class Bus extends Car{   //extends 클래스명    
    public void 승객을태우다(){
        System.out.println("손님이 탑니다.");
    }
}
class SeatBus extends Bus{
    public void 좌석을예약하다(){
        System.out.println("좌석이 예약 되었습니다.");
    }
}

class Truck extends Car{
    public void 짐을싣다(){
        System.out.println("짐을 싣습니다.");
    }
}
public class Exam01 {
    public static void main(String[] args) {
        Car car = new Car();
        car.name = "티코";
        car.speed = 100;
        System.out.println(car.name);
        System.out.println(car.speed);




        car.운행하다();
        // car.승객을태우다();

        Bus bus = new Bus();
        bus.name="스쿨버스";
        bus.speed = 80;

        System.out.println(bus.name);
        System.out.println(bus.speed);
        bus.운행하다();
        bus.승객을태우다();

        Truck truck = new Truck();
        truck.짐을싣다();
        truck.운행하다();

        //부모(조상)는 자식(자손)을 가리킬(담을) 수 있다.
        Car c = new Car();
        Car c2 = new Bus();
        Car c3 = new Truck();

        Truck t = new Truck();
        // Truck t2 = new Bus();
        // Truck t3 = new Car();

        SeatBus seatBus = new SeatBus();
        seatBus.name = "";
        seatBus.승객을태우다();
        seatBus.좌석을예약하다();

        //부모(조상)는 자식(자손)을 가리킬(담을) 수 있다.
        Car sb1 = new SeatBus();
        Bus sb2 = new SeatBus();

        Object obj = new Car();
        Object obj2 = new Bus();
        Object obj4 = new SeatBus();


        if(obj4 instanceof SeatBus) {
            SeatBus ss = (SeatBus) obj4;
            ss.좌석을예약하다();

            ((SeatBus) obj4).좌석을예약하다();
        }



        seatBus.좌석을예약하다();

        SeatBus sb = (SeatBus) sb1;
        sb.좌석을예약하다();

        ((SeatBus)sb1).좌석을예약하다();   //사용불가!!


    }
}



오버라이딩

package day06;

//오버라이딩
//부모가 가진것을 자식이 똑같이 다시 정의 할 수 있다.
class Parent {
    Parent(){
        System.out.println("Parent 생성자 실행");
    }
    int i = 5;

    public int getI() {
        return i;
    }
}
package day06;

class Child extends Parent {
    Child(){
        System.out.println("Child 생성자 실행!!");
    }
    int i = 10;   //i가 오버라이딩 된 상태.

    public int getI(){
        return i;
    }

    public void print(){
        System.out.println(i);
    }
}
package day06;

public class Exam06 {
    public static void test(Parent p){
        System.out.println(p.i);
        System.out.println(p.getI());
    }

    public static void main(String[] args) {
        Parent p = new Parent();
        System.out.println(p.i);
        System.out.println(p.getI());

        Child c = new Child();
        System.out.println(c.i);
        System.out.println(c.getI());

        Parent pc = new Child();
        System.out.println(pc.i);
        System.out.println(pc.getI());

        System.out.println("===================================");
        test(p);

        System.out.println("===================================");
        test(c);

        System.out.println("===================================");
        test(pc);
    }
}

pc.i가 5인 이유

Parent pc = new Child();

pc는 Child 객체를 참조하고 있지만, Parent 타입으로 선언되었기 때문에 필드 i에 접근할 때는 항상 Parent 클래스의 i = 5를 사용한다.




맛보기

✏️@Override annotation
java5부터 지원하는 @Override는 annotation인데, 안 써줘도 동작하지만 다음에 써준 코드가 정말 override가 맞는지 체킹해줌. 문법에 맞지 않으면 체킹 해줌!
Spring에서는 이러한 annotation을 많이 활용하므로 뒤에서 또 다룰 것임!

✏️super는 바로 위에 부모!
super()는 부모의 생성자

0개의 댓글