티스토리 뷰
요약
값을 리턴하는 함수를 만들때는 반드시 타입을 명시해야 한다
타입 추론
- 코틀린에서는 타입을 명시하지 않아도 변수가 선언될때 어떤 타입의 변수인지 추론해서 변수 선언이 가능하다
덕분에 코드량을 줄일 수 있다
추론된 타입 특징
(inferred타입 = 추론된 타입 이라는뜻이다)
1. 추론된 타입은 정확히 오른쪽에 있는 피연산자에 맞게 설정된다
open class Animal
class Zebra: Animal()
fun main() {
var animal = Zebra()
animal = Animal() // 오류 발생 타입 안맞음
}
위 코드를 보면 animal에 타입을 명시하지 않았다. 하지만 초기화할때 Zebra() 로 Zebra 타입을 넣어서 추론때문에 animal 의 타입은 Zebra 클래스이다
Zebra는 Animal을 상속받았다. animal 에 Animal 클래스를 넣으려 하니 오류가 생겼다. 업캐스팅이 안된다
open class Drinks{
var name :String = "음료수"
open fun Drink(){
println("${name}을 마십니다.")
}
}
class Cola : Drinks(){
var type :String = "콜라"
override fun Drink(){
println("${name}인 ${type}을 마십니다.")
}
fun Taste(){
println("${type}향이 납니다.")
}
}
fun main(){
var a: Drinks = Cola()
a = Drinks()
a.Drink()
}
위 코드처럼 하위 클래스로 명시한 변수에 상위 클래스를 넣는것을 업캐스팅이라고 한다. 그리고 위 코드는 잘 돌아간다
하지만

이렇게 타입 추론으로 변수를 만들어놓으면 그 변수는 업캐스팅이 안된다는것이다~
물론 이런 경우에는 변수를 만들때 타입을 명시하면 된다. 하지만 직접 명시를 못하는 상황(라이브러리 사용 등) 에서는 이런 문제가 간단히 해결되지 않는다
추론된 타입을 노출할때 생기는 문제
open class Car()
class NormalCar(): Car()
class ElectricCar(): Car()
val DEFAULT_CAR: Car = NormalCar()
interface CarFactory {
fun produce(): Car = DEFAULT_CAR
}
fun main(){
val carFactory = object: CarFactory {
override fun produce(): Car {
return super.produce()
}
}
val electricCarFactory = object: CarFactory {
override fun produce(): ElectricCar {
return ElectricCar()
}
}
var normalCar: Car = carFactory.produce()
var electricCar: ElectricCar = electricCarFactory.produce()
}
내가 자동차 생성 라이브러리를 만드는 개발자라고 가정하고 위와같은 코드를 만들었다고 하자
Car 클래스를 상속받는 NormalCar, ElectricCar 클래스 두개가 있고 차를 만들어주는 인터페이스를 만들었다고 치자
그 인터페이스의 produce는 기본적으로 NormalCar 인 DEFAULT_CAR 를 리턴한다
이렇게 만들어놓은 라이브러리를 사용자는 가져다 쓰면서 차도 만들고~ 전기차도 만들고~ 아주 행복한 시간을 보내고 있었다..
어느날 리팩토링을 하고싶어진 나..
val DEFAULT_CAR: Car = NormalCar()
interface CarFactory {
fun produce() = DEFAULT_CAR
}
어짜피 DEFAULT_CAR 에다가 Car로 명시했으니깐 ㅎㅎ produce에 명시해놓은 부분 지워야징 ㅋㅋ 해서 지움
그러다가 내가 퇴사함
그리고 그 자리에 상속? 이런거 모르는 사람이 들어왔다고 치자 혹은 새로 온 사람이 코드 숙지가 안됐다고 치자
val DEFAULT_CAR = NormalCar()
interface CarFactory {
fun produce() = DEFAULT_CAR
}
새로 들어온 사람이 ElectricCar 를 모르고 그냥
음.. DEFAULT_CAR 에 굳이 타입 명시를 해야되낭? NormalCar 리턴하는 그런거네 그냥~ 이러고 DEFAULT_CAR 에 명시해놓은 부분마저 지웠다
이렇게되면 해피해피해피~ 전기차 만들던 라이브러리 사용자가 띠용~!! ElectricCar, Car 둘다 못만들고 오직 NormalCar만 만들수있게 된다
이유는 위에서말한 타입추론 특징 때문!
타입 추론으로 변수를 초기화하면 그 변수에는 무조건 그 타입만 들어갈 수 있고 부모클래스 타입은 들어가지 못함
결론
- 타입을 확실히 지정해야 하는 경우에 명시적으로 타입을 적어주자
- 외부 API를 만들땐 쓰는 사람들을 위해서 타입을 명시하자
- 기존 코드에 있는 타입 명시를 함부로 지우지 말자
- 추론된 타입은 처음 만들어질땐 괜찮을수있지만 차후에 수정이 이루어질때 문제를 일으킬수있다
- 참고 사이트
https://velog.io/@ysh096/%EC%BD%94%ED%8B%80%EB%A6%B0-casting-is-as
코틀린 casting, is, as
클래스를 구현할 때 캐스팅이라는 개념이 있다.https://m.blog.naver.com/wnstn0154/221855117820https://altongmon.tistory.com/601업 캐스팅은 하위 클래스가 상위 클래스화 되는 것위의 코드에서는
velog.io
https://augustin26.tistory.com/m/27#google_vignette
[이펙티브 코틀린] Item4. inferred 타입으로 리턴하지 말라
코틀린의 타입 추론(type inference)은 널리 알려진 코틀린의 특징이며 자바도 자바10부터는 타입 추론을 도입했습니다. inferred 타입은 정확하게 오른쪽에 있는 피연산자에 맞게 설정되며 슈퍼클래
augustin26.tistory.com
https://bottom-to-top.tistory.com/66?category=1027392
아이템 4 - inferred 타입으로 리턴하지 말라
코틀린은 타입추론을 지원한다. 이 때 주의할 점이 있다. 먼저 추론된(inferred)타입은 정확하게 오른쪽에 있는 피연산자에 맞게 설정된다. 따라서 슈퍼클래스 혹은 인터페이스로 설정되지 않음을
bottom-to-top.tistory.com
'공부 > Kotlin' 카테고리의 다른 글
이펙티브 코틀린 1장 아이템6 - 사용자 정의 오류보다는 표준 오류를 사용하라 (0) | 2024.09.08 |
---|---|
이펙티브 코틀린 - 1장 아이템5 예외를 활용해 코드에 제한을 걸어라 (1) | 2024.08.18 |
이펙티브 코틀린 1장 아이템2 - 변수의 스코프를 최소화하라 (2) | 2024.06.10 |
이펙티브 코틀린 1장 아이템1 - 가변성을 제한하라 (0) | 2024.06.09 |
null 관련 연산자(안전 호출 연산자, 어설션 연산자, 엘비스 연산자) (0) | 2022.10.29 |