List
첫 번째 또는 마지막 항목 (비아 포인트)이 아닌 모든 항목을 반환하는 함수를 작성하고 싶습니다 . 이 함수는 제네릭 List<*>
을 입력으로 가져옵니다 . 목록의 요소가 다음 유형 인 경우에만 결과가 반환되어야합니다 Waypoint
.
fun getViaPoints(list: List<*>): List<Waypoint>? {
list.forEach { if(it !is Waypoint ) return null }
val waypointList = list as? List<Waypoint> ?: return null
return waypointList.filter{ waypointList.indexOf(it) != 0 && waypointList.indexOf(it) != waypointList.lastIndex}
}
를 캐스팅하는 경우 List<*>
에 List<Waypoint>
, 나는 경고를 얻을 :
체크되지 않은 캐스트 : kotlin.collections.List에서 kotlin.colletions.List로
나는 그것을 구현하는 방법을 알아낼 수 없습니다. 이 경고없이이 기능을 구현하는 올바른 방법은 무엇입니까?
답변
Kotlin에서는 일반적으로 런타임에 일반 매개 변수를 확인할 수있는 방법이 없습니다 (예 List<T>
: 특수한 경우 일 뿐인 의 항목 확인 ). 따라서 다른 일반 매개 변수를 사용하여 일반 유형을 다른 유형으로 캐스팅하면 경고가 발생합니다. 캐스트는 분산 범위 내에 있습니다 .
그러나 다른 솔루션이 있습니다.
-
유형을 확인했으며 캐스트가 안전하다고 확신합니다. 그 감안할 때, 당신은 할 수 있습니다 경고 억제 와를
@Suppress("UNCHECKED_CAST")
.@Suppress("UNCHECKED_CAST") val waypointList = list as? List<Waypoint> ?: return null
-
.filterIsInstance<T>()
항목 유형을 확인하고 전달 된 유형의 항목이있는 목록을 반환하는 함수를 사용 합니다.val waypointList: List<Waypoint> = list.filterIsInstance<Waypoint>() if (waypointList.size != list.size) return null
또는 한 문장에서 동일합니다.
val waypointList = list.filterIsInstance<Waypoint>() .apply { if (size != list.size) return null }
이렇게하면 원하는 유형의 새 목록이 생성되어 (따라서 내부에 확인되지 않은 캐스트 방지) 약간의 오버 헤드가 발생하지만 동시에
list
유형 을 반복 하고 확인하는 작업 (list.foreach { ... }
인라인)을 절약 할 수 있습니다. 눈에.니다. -
유형을 확인하고 유형이 올바른 경우 동일한 목록을 반환하는 유틸리티 함수를 작성하여 그 안에 캐스트를 캡슐화합니다 (컴파일러의 관점에서 여전히 확인되지 않음).
@Suppress("UNCHECKED_CAST") inline fun <reified T : Any> List<*>.checkItemsAre() = if (all { it is T }) this as List<T> else null
사용법 :
val waypointList = list.checkItemsAre<Waypoint>() ?: return null
답변
@hotkey의 답변을 개선하려면 여기에 내 솔루션이 있습니다.
val waypointList = list.filterIsInstance<Waypoint>().takeIf { it.size == list.size }
이렇게 List<Waypoint>
하면 모든 항목을 캐스트 할 수 있는지 여부를, 그렇지 않으면 null을 제공합니다.
답변
제네릭 클래스의 경우 런타임에서 유형 정보가 지워지기 때문에 캐스트를 확인할 수 없습니다. 그러나 목록의 모든 개체가 Waypoint
s 인지 확인 하여을 사용하여 경고를 억제 할 수 있습니다 @Suppress("UNCHECKED_CAST")
.
이러한 경고를 피하려면 List
로 변환 할 수있는 객체 를 전달해야합니다 Waypoint
. 사용 *
중이지만 입력 된 목록으로이 목록에 액세스하려는 경우 항상 캐스트가 필요하며이 캐스트는 선택 취소됩니다.
답변
Serializable to List 객체를 확인하는 데 사용할 때 @hotkey 대답에 약간의 변형을가했습니다.
@Suppress("UNCHECKED_CAST")
inline fun <reified T : Any> Serializable.checkSerializableIsListOf() =
if (this is List<*> && this.all { it is T })
this as List<T>
else null
답변
대신에
myGenericList.filter { it is AbstractRobotTurn } as List<AbstractRobotTurn>
나는하는 것을 좋아한다
myGenericList.filter { it is AbstractRobotTurn }.map { it as AbstractRobotTurn }
이것이 얼마나 성능이 좋은지는 확실하지 않지만 적어도 경고는 없습니다.