2016-12-12 24 views
5

Ben generic'leri kullanan aşağıdaki kod:KOTLIN en Jenerik: jenerik haritası parametrede tür uyuşmazlığı

abstract class Event(val name: String) 

interface ValueConverter<E : Event> { 

    fun convert(event: E): Float 

    fun getEventClass(): Class<E> 

} 

class ValueConverters { 

    private val converters = HashMap<String, ValueConverter<Event>>() 

    fun <E : Event> register(converter: ValueConverter<E>) { 
     converters.put(converter.getEventClass().name, converter) 
    } 

    fun unregister(eventClass: Class<Event>) { 
     converters.remove(eventClass.name) 
    } 

    fun <E : Event> convert(event: E): Float { 
     return converters[event.javaClass.name]?.convert(event) ?: 0.0f 
    } 

    fun clear() { 
     converters.clear() 
    } 

} 

Ama bu hat üzerinde:

Type mismatch. Expected ValueConverter<Event>. Found ValueConverter<E>.

:

converters.put(converter.getEventClass().name, converter) 

bir hata veriyor

Ayrıca böyle bir şey denedim:

class ValueConverters { 

    private val converters = HashMap<String, ValueConverter<Event>>() 

    fun register(converter: ValueConverter<Event>) { 
     converters.put(converter.getEventClass().name, converter) 
    } 

    fun unregister(eventClass: Class<Event>) { 
     converters.remove(eventClass.name) 
    } 

    fun convert(event: Event): Float { 
     return converters[event.javaClass.name]?.convert(event) ?: 0.0f 
    } 

    fun clear() { 
     converters.clear() 
    } 

} 

Fakat böyle bir şeyle ValueConverters.register() çağrılırken sorunudur:

class SampleEvent1 : Event(name = SampleEvent1::class.java.name) 

class SampleValueConverter1 : ValueConverter<SampleEvent1> { 

    override fun convert(event: SampleEvent1): Float = 0.2f 

    override fun getEventClass(): Class<SampleEvent1> = SampleEvent1::class.java 

} 

converters.register(converter = SampleValueConverter1()) 

Ayrıca benzer tür uyuşmazlığı hatası veriyor.

Jenerik değerlerini, ValueConverter uygulayan ve Event'i genişleten herhangi bir sınıfı kabul eden herhangi bir sınıfı kullanabilmem için nasıl bildirmeliyim?

cevap

8

hata bu hat üzerindedir: Bu haritanın

private val converters = HashMap<String, ValueConverter<Event>>()

değerleri ValueConverter<Event> ile sınırlıdır.

ValueConverter<FooEvent>,

haritanızda bu değer dönüştürücü saklamak olamazdı: Bir sınıf

class FooEvent : Event

ve bir değer converter var ise. Gerçekte istediğiniz şey bir * yıldız projeksiyon tipidir.

private val converters = HashMap<String, ValueConverter<*>>()

Şimdi haritasında ne olursa olsun değer dönüştürücü koyabilirsiniz. Nasıl

fun <E : Event> convert(event: E): Float

haritası döndü konvertör genel tür ne olduğunu biliyor:


Ancak bu başka bir sorun ortaya çıkarır? Sonuçta, harita farklı etkinlik türleri için birden fazla dönüştürücü içerebilir!

IntelliJ derhal yakınır:

Out-projected type 'ValueConverter<*>?' prohibits the use of 'public abstract fun convert(event: E): Float defined in ValueConverter'.

Ama harita anahtarı genel tür parametresi adıdır çünkü zaten genel tür biliyorum!

@Suppress("UNCHECKED_CAST") 
fun <E : Event> convert(event: E): Float { 
    val converter = converters[event.javaClass.name] ?: return 0.0f 
    return (converter as ValueConverter<E>).convert(event) 
} 

Merak ediyorsanız derleyici daha erken dönüştürücü işlevi hakkında şikayet etmedi neden:: Harita sadece ValueConverter<Event> tutunabileceği nasıl hatırla

Yani basitçe kuvvetle harita tarafından döndürülen değer dağıtmak ve sadece bu sınıf? Bu, derleyicinin Event'un herhangi bir alt sınıfını bu dönüştürücüye geçirebileceğinizi bildiği anlamına gelir. hiçbir şey çünkü

: Haritanızdaki convert(event: Nothing) belirli bir dönüştürücü etkili fonksiyonu imzasını yapma - Bir yıldız projeksiyon tipi değişti sonra bu vb ValueConverter<FooEvent> veya ValueConverter<BazEvent>, olabilir eğer derleyici bilmez geçerli bir girdidir.

+0

Teşekkürler! İşe yarıyor. –