상속

Muhly·2023년 3월 23일
0

oop

목록 보기
8/8

안녕하세요🤗10기ssafy를 목표로 열심히 달리고 있는 Muhly라고 합니다.저의 벨로그는 저의 창작물도 있겠지만 다른 유명한 강사님들과 블로거분들의 글들이 많이 포함하고 있습니다.이 벨로그는 저의 스터디 노트와 일상 기록용입니다.

✏️상속이란?

상속은 계층화를 통해 부모, 자식이라는 관계를 수직적으로 설계하는 기술이다.
공통된 부분을 Animal클래스에서 구현하고 자식은 해당 동작을 쉽게 가져다 쓸 수 있도록 extnds를 통해서 상속관계를 만들어준다.

💡 상속체이닝 구조: object> Animal>Cat=Dog

자바에서 최상위 Root클래스는 Object클래스이다.
눈에는 안보이지만 모든 클래스에는 부모로 명시된 extends Object가 있다.
또한, super()도 눈에 보이지 않는 기본 생성자로 사용되므로 하나의 클래스가 실행될때 super()는 자식이 아니라 부모부터 생성하기 때문에 Object가 생성되고 Animal이 생성된다. Animal을 생성한 뒤에 Dog,Cat을 만드는 것과 같은 원리이다.

✏️수평적 설계와 수직적 설계

💡수평적 설계(기본적 설계)

  1. 코드의 중복이 발생
  2. 새로운 요구사항에 대한 코드의 수정이 불가피하다.
  3. 관리하기가 어렵다.
public class Dog{
	public void eat(){
    	System.out.println("개는 먹는다");
        }
      }
public class Dog{
	public void eat(){
    	System.out.println("고양이는 먹는다");
        }
      }

public class Basic {
    public static void main(String[] args) {
 
    Dog dog = new Dog();
    dog.eat();
 
    Cat cat = new Cat();
    cat.eat();
 
   }
}

클래스 설계시 Dog와 Cat을 만들게 되었는데 어라라...eat()이라는 행위는 중복되었다.그러면 이외에도 다른 동물 들이 있다면 모든 동물에 eat()을 만들어야한다는데 그렇다면 관리도 어렵고 수정하기도 어렵다.

💡수직적설계(상속)


public class Animal {
    public void eat() {
        System.out.println("뫄뫄가 먹는다.");
    }
 
}
public class Dog extends Animal {
 
}
// Cat도 동일
public class Basic {
    public static void main(String[] args) {
 
    // 1. 자식으로 받음        
    // Dog dog = new Dog();
    // dog.eat();
     
    // 2. 부모로 받음
    // 부모-자식간의 자동 형변환, 업캐스팅이 된다.
    Animal ani = new Dog();
    ani.eat();
        
    ani = new Cat();
    ani.eat();   }
}

만약 Dog, Cat의 중복적인 속성을 밖으로 빼서 하나의 클래스로 만들면 어떻게 될깝쇼?
이들의 부모인 Animal에만 eat()를 만들어서 상속한다면
코드는 복잡해지지만 유지보수 측면에서 훨씬 이점이 많을 것입니다.

상속을 할 때는 자식 클래스에서 extends를 붙이는데 '나를 확장해서 부모까지 영향을 행사한다' 정도로 볼 수 있다.즉, Dog와Cat의 기능은 더욱 많아지는거죠.

이 클래스를 사용할 때는 보통 자식 클래스에서 생성하여 받는 것보다 부모 클래스에서 생성한다.

✏️Override(재정의)

상속의 재정의란?
상속관계에서 상속받은 하위 클래스가 상위 클래스의 동작을 수행하는 것
(상속받은 자식 클래스가 부모클래스의 동작을 수행하는 것)

❗️조심조심_재정의는 어떨때 시켜주나요?

상속에서 아쉬운점을 찾는다면 뫄뫄가 먹는다라고 썼는데 Dog는 "개가 먹는다"cat은 "고양이가 먹는다"이렇게 쓰고싶다.그런데 이렇게 할수 있는 방법이 뭐다?
바로 재정의를 시켜주는 것이다.

  1. 부모클래스 Animal
package kr.tpc;

public class Animal {
    //개와 고양이의 공통 행동부분
    public void eat(){
        System.out.println("뫄뫄가 먹는다");//포괄적, 추상적_고영이처럼먹는다하면 다 고양이됨
    }
}
  1. 자식클래스 Cat, Dog
package kr.tpc;

public class Dog extends Animal {
    public void eat(){
        System.out.println("개처럼 먹다");
    }
}
package kr.tpc;

public class Cat extends Animal {
//    public void eat(){
//        System.out.println("고영이처럼 먹다");
//    }->빠짐
    public void night(){
        System.out.println("밤에 눈에서 빛이 난다");
    }

    @Override
    public void eat() {
        System.out.println("고양이처럼 먹다");
    }
}
  1. 실행클래스
package oop;

import kr.tpc.Animal;
import kr.tpc.Cat;
import kr.tpc.Dog;

public class TPC20 {
    public static void main(String[] args) {



        Animal ani = new Dog();//업캐스팅_자동형변환
        ani.eat();

        ani = new Cat();
        ani.eat();
        ((Cat)ani).night();//다운캐스팅_강제 형변환
    }
}
개처럼 먹다
고양이처럼 먹다
밤에 눈에서 빛이 난다

💡자식으로 받는 경우와 부모로 받는 경우가 있는데 부모로 받는 경우만 설명하겠다.

1.부모로 받음(기본적/업캐스팅)

1.Animal ani = new Dog();로 객체를 만들면 마찬가지로 super()를 통해 부모인 Animal()객체가 메모리에 먼저 생성된 뒤에 Dog()객체가 생성된다.

2.Dog()객체는 Animal타입이기 때문에 ani가 메모리를 가리키게 될때 Animal의 범위에만 도달할 수 있다.

3.만약 재정의를 할 경우 같은 메서드라면 재정의를 했는지 찾아가게 디ㅗ어있고 재정의가 되어있을 경우에는 Dog의 메서드가 실행된다.(동적 바인딩)

=> ani.eat(); 의 컴파일 시점에서는 부모의 eat()인데 실행될 때는 동적 바인딩을 통해서자식에게 재정의된 메서드를 찾고 Dog()에 eat()가 재정의되어 있다면 그걸 선택한다.
4.즉, Dog의 기능을 몰라도 부모의 타입으로 Dog의 메서드를 재정의할 수 있다.

2. 난 좀 달라(다운 캐스팅)

만약 자식의 메서드 중에 재정의 되지 않은 메서드는 부모 타입으로 만들때 어떻게 해야할까? 이럴때는 다운 캐스팅이 필요하다.부모의 타입을 자식의 타입으로 강제 형변환해야한다.

profile
https://muhlysstudynote.tistory.com/-> 블로그 이전하였습니다

0개의 댓글