객체지향의 원칙중 하나인 LSP (리스코프 치환 원칙) 의 위키백과에는 아래와 같은 내용이 존재한다.
리스코프의 원칙은 새로운 객체 지향 프로그래밍 언어에 채용된 시그니처에 관한 몇 가지 표준적인 요구사항을 강제한다. |
핵심단어는 공변성과 반공변성이다.
공변성(Covariance)
Animal 클래스를 상속받은 Dog 클래스가 있다.
Animal 과 Dog은 상속관계이므로
Animal animal = new Dog();
이 가능하다.
그럼
IEnumerable<Animal> animals = new List<Dog>();
은 가능할까?
정답은 가능하다. 그리고 자연스럽게 위처럼 프로그래밍한적이 있었을것이다.
그런데 이것이 어떻게 가능한것일까? 우리가 상속 관계를 표현한것은 Animal 과 Dog 이지 IEnumerable<Animal> 과의 관계가 아니다.
이것을 가능한 이유는 IEnumerable 인터페이스는 공변성 을 가지고 있기 때문이다.
X -> Y일때 C<T>가 C<X> -> C<Y>라면 공변이다.
C# 에서는 Generic 을 사용할때 out키워드를 붙여주는것으로 공변이라는것을 알려준다.
public interface IEnumerable<[NullableAttribute(2)] out T> : IEnumerable
{
///
}
IEnumerable 타입에의 T 앞에 out 키워드가 있는것을 확인할수있다.
반공변성 (Contravariance)
X -> Y일때 C<T>가 C<X> -> C<Y> 가 공변이라면 반공변은 반대로
X -> Y일때 C<T>가 C<Y> -> C<X> 이다.
공변성이야 자식관계과 인터페이스 동일하게 에서도 적용된다는 느낌으로 이해가 된다.
그런대 반공변성은 쉽게 이해가 되지 않는다. 반공변성은 왜 필요한것일까?
위에서 확인할수 있듯이 Action 델리게이터의 경우 반공변으로 선언되어있다.
Animal 이 할수있는 함수의 경우 Dog 이 할수있을까? 할수있다. Animal을 상속받았으니까
-> 즉 Play(Animal animal) 에 Play(dog) 이 가능하다.
Dog 이 할수있는일을 Animal이 할수있을까? 할수없다. 뭔지 모르기 때문이다.
-> 즉 Play(Dog dog) 에 Play(animal) 은 불가능하다.
static Action<Dog> GetPlayDogAction ()
{
return (d) => d.Play();
}
static Action<Animal> GetPlayAnimalAction()
{
return (a) => a.Play();
}
static void Main(string[] args)
{
Animal ani = new Animal();
Dog dog = new Dog();
Action<Animal> playAnimalActionToAnimal = GetPlayAnimalAction();
Action<Dog> playAnimalActionToDog = playAnimalActionToAnimal;
Action<Dog> playDogActionToDog = GetPlayDogAction();
//Action<Animal> playDogActionToAnimal = playDog; //Error
playAnimalActionToAnimal(ani);
playAnimalActionToDog(dog);
playDogActionToDog(dog);
}
즉 Action<Dog> 에 Action<Animal> 을 넣는것은 가능하다.
그러나 Action<Animal> 에 Action<Dog> 을 넣는것은 불가능하다.
IEnumerable<Animal> 에 new List<Dog> 을 넣는것과정 반대의 상황이다.
이를 반공변이라고 한다.
'프로그래밍 언어 노트 > C#' 카테고리의 다른 글
[C#/WPF] ObservableCollection, List 간의 변환 (0) | 2020.06.03 |
---|---|
[C#] Welcome To C# 9.0 [C# 9.0 변경사항 (예상)] (0) | 2020.05.22 |
[C#/Winform] ElementHost 를 이용하여 WinForm 에서 WPF 컨트롤 호스팅 (0) | 2020.05.14 |
[C#] C# 버전별 주요 변화 (0) | 2020.04.01 |
[C#] 닷넷의 기본 파일 처리함수는 부정확할 수 있다 (0) | 2020.02.25 |