Skip to content

Commit

Permalink
Docs: Add Strongly Typed, Flexibly Polymorphic/Chapter03.md
Browse files Browse the repository at this point in the history
  • Loading branch information
fkdl0048 committed Feb 11, 2025
1 parent 4568d29 commit 51fc6dc
Showing 1 changed file with 73 additions and 0 deletions.
73 changes: 73 additions & 0 deletions Strongly Typed, Flexibly Polymorphic/Chapter04.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
## 두 다형성의 만남

### 제네릭 클래스와 상속

```cs
abstract class List<T>
{
T get(int index);
}
```

- *C#의 제네릭 클래스는 불변이다.*

다음과 같은 추상 클래스를 상속받아 서브타입 클래스를 만들었을 때, 앞서 다룬 제네릭과 같이 서브타입 클래스의 제네릭 타입은 부모 클래스의 제네릭 타입을 따른다.

```cs
class ArrayList<T> : List<T>
{
T get(int index) { ... }
}
```

여기서 핵심은 상속받는 추상 클래스의 제네릭 타입을 `T`로 정의했기에 서브타입 클래스에서도 제네릭의 특성을 이용하고 싶다면 `T`로 정의해야 한다는 것이다. A가 B를 상속하면 A가 B의 서브타입이기 때문에 이 원리 그대로 제네릭 클래스에도 적용된다.

반대로 제네릭의 특성을 이용할 필요가 없기 타입이 명확한 서브타입을 만들고 싶다면 제네릭 타입을 명시적으로 정의해야 한다.

```cs
class IntArrayList : List<int>
{
int get(int index) { ... }
}
```

### 타입 매개변수 제한

앞서 3장에서 정리한 내용과 같이 제네릭 함수의 경우 매개 변수가 아무 타입이나 나타낼 수 있다고 가정하기에 타입 변수 T에 대해서 출력하거나 반환할 수는 있어도 덧셈이나 곱셈과 같이 특별한 능력이 필요한 곳에는 사용할 수 없다고 했다. 이 내용은 사용 의도 자체를 잘 나타내는 것으로 제네릭 함수를 정의하는 것은 결국 여러 타입으로 사용될 수 있는 함수를 만드는 것이고, 인자가 특별한 능력을 가져야 한다면 그 함수는 여러 타입으로 사용될 수 없다.

*3장에 대한 추가 정리 내용*

```cs
class Person
{
int age;
...
}

class Student : Person {...}

Person Elder(Person p1, Person p2)
{
return p1.age > p2.age ? p1 : p2;
}

Student s = elder(s1, s2);
```

위 코드는 타입 검사기를 통과하지 못한다. 정확하게는 `elder(s1, s2)`까지는 타입 검사를 통과한다. Student는 Person의 서브타입이기 때문에 Person 타입으로 반환할 수 있다. 하지만 결과를 Person으로 반환하는 순간 Student 타입으로 다운 캐스팅해야 하기 때문에 타입 검사를 통과하지 못한다.

이 경우 실제 메모리에 적재된 객체가 분면 Student 타입임을 알지만 문제가 된다. *정적 타입 검사이기 때문* 이를 해결하기 위해 제네릭 함수로 교체한다고 해도 .age 필드 값을 읽으려 했기 때문에 여전히 타입 검사를 통과하지 못한다.

이 상황을 해결하기 위해선 타임 **매개변수 제한**이라는 기능이 필요하다. *C#에서는 where 절을 사용한다.* 직관적인 해석은 T가 최대 Person타입까지 커질 수 있음을 나타낸다. 3장에서 예로 INumber<T>를 사용한 것과 같은 방식이다.

이전까지 제네릭 함수가 아무 타입이나 인자로 받을 수 있던 것과 달리, 타입 매개변수 제한을 사용한 제네릭 함수를 사용할 때는 정의된 상한을 타입 인자가 따라야 한다. *함수뿐만 아니라 클래스도 사용 가능하다.*






### 정리

개인적으로 `C#`의 IEnumerable에 대해서 공부할 때 해당 내용을 정리한 경험이 있어서 잘 이해가 된 것 같다. 당시에도 어렵게 이해한 내용이 많았고, C# 키워드에서도 `in`, `out`키워드가 존재해서 좀 더 쉽게 이해한 것 같다.

0 comments on commit 51fc6dc

Please sign in to comment.