整数は、あなたがそれを行うことができる方法である。
object Main {
// concrete class for all "enum" values (such as OfferType.ADDON or OfferType.SALE)
// that get passed to `getOffer` as second param
class OfferType<T> {
companion object Types {
// "enum" values. Unfortunately Kotlin doesn't support
// type parameters for real enums
@JvmStatic
val ADDON = OfferType<Addon>()
@JvmStatic
val SALE = OfferType<Sale>()
data class Addon(val name: String)
data class Sale(val name: String)
}
}
data class OfferRepresentation(
val addon: OfferType.Types.Addon,
val sale: OfferType.Types.Sale
)
@JvmStatic
fun main(args: Array<String>) {
fun <T> getOffer(offers: OfferRepresentation, type: OfferType<T>): T {
@Suppress("UNCHECKED_CAST")
return when (type) {
OfferType.ADDON -> offers.addon as T
OfferType.SALE -> offers.sale as T
else -> throw IllegalArgumentException("Unsupported type $type")
}
}
val offer = OfferRepresentation(
OfferType.Types.Addon("addon"),
OfferType.Types.Sale("sale")
)
// types are specified explicitly for the sake of demonstration
val addon: OfferType.Types.Addon = getOffer(offer, OfferType.ADDON)
val sale: OfferType.Types.Sale = getOffer(offer, OfferType.SALE)
println("$addon, $sale")
}
}
注UNCHECKED_CAST
getOffer
内の関数があること。 OfferType.ADDON
(OfferType.SALE
など)の値が正しいOfferRepresentation
のフィールドタイプでパラメータ化され、when
ロジックも正しく設定されていることを確認することは、あなたの責任です。そうでなければ、実行時にClassCast
例外が発生します。
UPD。コットリンの魔法を少し使った別の実装、具体的にはreified typesがあります。この手法では、別のエンティティを持つフィールドを定義する代わりに、getOffer
関数から返される戻り値の型パラメータを指定するだけです。別の方法としては、暗黙の型推論に頼ることができます。
object Main2 {
object OfferType {
data class Addon(val name: String)
data class Sale(val name: String)
}
data class OfferRepresentation(
val addon: OfferType.Addon,
val sale: OfferType.Sale
)
//reified type parameters require function to be inline
inline fun <reified T> getOffer(offers: OfferRepresentation): T {
@Suppress("UNCHECKED_CAST")
return when (T::class) {
OfferType.Addon::class -> offers.addon as T
OfferType.Sale::class -> offers.sale as T
else -> throw IllegalArgumentException("Unsupported type ${T::class}")
}
}
@JvmStatic
fun main(args: Array<String>) {
val offer = OfferRepresentation(
OfferType.Addon("addon"),
OfferType.Sale("sale")
)
// types needed to be specified explicitly here
val addon: OfferType.Addon = getOffer(offer)
val sale: OfferType.Sale = getOffer(offer)
// alternatively `getOffer` should be invoked like this:
getOffer<OfferType.Addon>(offer)
println("$addon, $sale")
}
}
OfferRepresentationクラスの外観はどうなっていますか? – fejd
@fejd OfferRepresentationには、addon、sale、planまたはcustomPlanの4つの属性(offerTypes)があります。 OfferRepresentationに計画(または他のもの)がある場合、他の属性は必ずnullです。 –