서브 타입

김동현·2024년 7월 9일

Study

목록 보기
7/8

Sub + Type

sub

+ type(형(태), 유형, 종류)

서브 타입은 어떠한 형태 보다 더 작은 형태의 타입을 말한다.

🤔 더 작은 타입이란 무슨 뜻일까?

타입의 관점에서 더 작다는 뜻은 포함된다라는 뜻이다.

예를 들면 숫자 1은 숫자 타입에 포함된다.
예를 들면 문자 'a'는 문자 타입에 포함된다.
예를 들면 참 True는 불 타입에 포함된다.

즉, A가 B에 포함될 때 A는 B의 서브 타입이라고 한다.

예를 들면 숫자 1은 숫자 타입이다.
예를 들면 문자 'a'는 문자 타입이다.
예를 들면 참 True는 불 타입이다.

즉, A가 B타입일 때 A는 B의 서브 타입이라고 한다.

서브타입이 왜 필요할까?

다형성(多 많을 다 形 모양 형 性 성품 성) 때문이다.
다형성이란 하나의 타입이 다양한 형태(타입)이 될 수 있다는 뜻이다.

🤔 만약, 다형성이 없다면 어떤 일이 일어날까?
우리는 정적 언어를 사용하면서 알게 모르게 다형성을 십분 활용한다.

✅ 다형성이 없다면 타입은 엄격해진다.

아래의 두 코드를 한 번 살펴 보자

type Type = {foo: string}
type SubType  = {foo: string, bar: string}

var t: Type = {foo: "1", bar: "1"} // bar does not exist in type Type

위 코드는 에러가 발생한다. bar does not exist in type Type bar라는 프로퍼티가 Type이라는 타입에 존재하지 않는다는 것이다.

하지만, 아래의 코드는 에러가 발생하지 않는다.

type Type = {foo: string}
type SubType  = {foo: string, bar: string}

var t: Type = {foo : "hello"}
var s: SubType = {foo: "1", bar: "1"}

// b = t
t = s

console.log(t) // {foo: "1", bar: "1"}

서브 타입에 의한 다형성이 인정되지 않는다면, 변수 t에는 오로지 foo 프로퍼티가 존재하는 객체만이 담길 수 있게 될 것이고,
❗️ 두 번째 예시의 코드 또한 변수에 값 할당시 변수를 초기화 할 때처럼 에러가 발생 했을 것이다!

서브 타입 덕에 우리는 타입을 유연하게 사용할 수 있게 된다.

타입은 집합과 유사하다
만약 우리가 number 만들어 올 수 있다고 했다.

근데 숫자 1이라는 녀석이 문 앞에서 다음과 같이 외치고 있다면 어떤 생각이 들까?

📢 나는 1 이라서 못들어가!!!
😇 ??? 야 너도 number야 괜찮아 들어와!!

💡서브 타입의 소중함이다.

이름에 의한 vs 구조에 의한 서브타입

  1. 이름에 의한 서브타입(Nominal Subtyping)을 사용하는 언어는 자바가 있다.

이름에 의한 서브타입은 아주 직관적이다.

타입의 이름과 선언을 통해 서브타입 관계를 정의한다.
즉, 한 타입이 다른 타입의 서브타입이 되기 위해서는 명시적으로 그 타입을 상속받거나 구현하는 것이다.

아래의 코드는 Dog 클래스가 Animal 클래스를 명시적으로 상속 받고 있다.
즉, Animal 클래스는 Dog 클래스의 서브타입이다.

class Animal { }

class Dog extends Animal { }
  1. 구조에 의한 서브 타입을 사용하는 언어로는 Typescript가 있다.

구조에 의한 서브 타입(Structural subtyping)은 프로퍼티와 메서드의 형태를 통해 서브타입 관계를 정의한다.
타입의 이름은 중요하지 않으며, 구조적으로 동일한 형태를 가지면 서브타입으로 간주하는 것이다.

즉, 어떠한 객체나 클래스가 다른 객체나 클래스의 멤버 변수와 메서드를 가지고 있다면 구조적으로 서브 클래스라고 간주하게 된다.

class Animal {
    name: string;
    speak(): void {
        console.log("Some generic animal sound");
    }
}

class Dog {
    name: string;
    speak(): void {
        console.log("Woof!");
    }

Dog 클래스는 Animal 클래스를 상속 받지 않았다.
하지만, Animal 클래스가 가지고 있는 name 변수, speak 메서드가 있기에 서브타입이다!

🤔 상속 시 자바 메모리 구조

김영한 선생님의 자바 강의에서 상속 시 메모리 구조에 대한 내용이 나온다.

new Dog()로 인스턴스를 생성하게 되면 힙 메모리에 데이터가 생성 되게 된다.
하지만 이 때 Dog에 대한 변수와 메서드만 생성되는 것이 아니라,
명시적으로 상속 받은 슈퍼 타입의 값들도 함께 생성되게 된다.

즉, 인스턴스 생성 시 AnimalDog의 변수들이 함께 생성되게 되는 것이다.
이런 방법은 슈퍼 타입의 값들에 접근하는 데 굉장히 효율이 좋을 것이다.

구조적인 서브 타입을 가져갈 이유가 없다!

🔥 위 예시를 보면 둘의 차이를 조금 느낄 수 있지 않을까

profile
달려보자

0개의 댓글