공변 반환 타입(covariant return types) 메커니즘은 자바에서 메서드를 재정의(overriding)할 때 슈퍼클래스와 정확히 동일한 타입 대신 그 하위 타입(covariant type)을 반환할 수 있도록 합니다.
이는 명시적 캐스팅 없이 더 구체적인 타입을 얻을 수 있어 코드의 표현력을 높입니다.
예제:
class Animal { } class Dog extends Animal { } class Parent { Animal getAnimal() { return new Animal(); } } class Child extends Parent { @Override Dog getAnimal() { return new Dog(); } // 공변 반환 }
작동 조건:
서브클래스에서 오버로드된 메서드의 반환 타입을 기본 타입의 하위 타입으로 변경할 수 있습니까? 이것이 유효한 오버로드로 간주될까요?
답변: 아니요, 오버로딩(overloading)에서는 매개변수에 대한 시그니처만 중요하며 반환 타입은 중요하지 않습니다. 오버로드에서 반환 타입만 변경할 수는 없으며, 그렇게 할 경우 메서드 시그니처가 충돌하게 됩니다.
예제:
class Example { Animal make() { return new Animal(); } // Dog make() { return new Dog(); } // 컴파일 오류: 중복 메서드! }
공변성은 오버라이딩(overriding)에서만 작동합니다.
이야기
프로젝트에서 프로그래머가 같은 이름과 매개변수를 가진 오버로딩 메서드를 추가했지만 반환 타입이 다르다는 실수를 범하여 이를 "공변 재정의"가 될 것이라고 기대했습니다. 결과적으로 프로젝트는 컴파일되지 않았고, 이 버그는 CI 중에 발견되었습니다.
이야기
클래스 계층에서 공변 반환을 사용할 때, 개발자가 하위 타입을 제대로 구현하지 않고 매개변수화된 타입(generics)을 잘못 적용하여 컬렉션 작업 중 실행 시 ClassCastException 오류가 발생했습니다.
이야기
재정의된 메서드에서 더 특수화된 타입을 반환했으나 팀에서 이 계약을 문서화하지 않았습니다. 기본 타입을 통해 작업하는 코드에서 타입 캐스팅의 어려움과 "업캐스트(upcast)" 참조 시 예상치 못한 동작이 발생하여 여러 숨겨진 오류가 발생했습니다.