2014-10-09 16 views
5

genişletir İki izomorfik hiyerarşim var. Birincisinin taban tipi BaseA ve ikincisinin baz tipi BaseB'dir. BaseB'nin herhangi bir alt sınıfının herhangi bir nesnesini BaseA'nın ilgili alt türüne nasıl dönüştüreceğini biliyorum. BaseB türünü nesneyi alan bir yöntemi uygulamak istiyorum ve sınıfını belirler ve BaseA'nın ilgili alt türünün bir nesnesini oluşturur. Örnek kod:Java jenerik: <B BaseB> uzantıları eşleşmiyor <? BaseB>

public interface BaseA... 
public interface BaseB... 
public class DerA implements BaseA... 
public class DerB implements BaseB... 
... 
public interface Transform<A,B> { 
    A toA (B b); 
} 

public class DerAtoDerB implements Transform<DerA,DerB> { 
    DerA toA (DerB b){...} 
} 

public class Transformations { 
    private static Map<Class<?>, Transform<? extends BaseA, ? extends BaseB>> _map = 
     new HashMap<>(); 
static { 
    _map.put(DerB.class, new DerAtoDerB()); 
    } 

public static <B extends BaseB> BaseA transform(B b){ 
    Transform<? extends BaseA, ? extends BaseB> t = _map.get(b.getClass()); 
    return t.toA(b); // Compile error: Transform<A,B#2> cannot be applied to given types 
} 

Neden <B extends BaseB><? extends BaseB> ile uyumlu değildir? Transform<A,B> cannot be applied to given types

kimse ben Generics yanlış yapıyorum bana açıklayabilir:

public static BaseA transform(BaseB b){ 
    Transform<? extends BaseA, ? extends BaseB> t = _map.get(b.getClass()); 
    return t.toA(b); // Compile error: Transform<A,B> cannot be applied to given types 
} 

Bir derleme hatası alıyorum: Böyle statik dönüşümü yöntemi uygulamayı deneyin Ayrıca olur?

+0

İlk cevap size http://stackoverflow.com/questions/16449799/how-do-generics-of-generics-work – aalku

cevap

-2

Temel Java javascript kavramı: ChildClass ParentClass'ı genişletirse, YourApi < ChildClass> YourApi < ParentClass> öğesini genişletir. Ör:

NumberTransform<String, ? extends Number> intTransform = new IntegerTransform<String, Integer>(); // work with Integer numbers only 
NumberTransform<String, ? extends Number> longTransform = new LongTransform<String, Long>();  // work with Long numbers only 

longTransform.toA((Integer) 1); // you are trying to make this and got compilation error. 

derleyici sizin t başlatma değiştirmek yardımcı olmak için: derleyici gönderildiği eşleşir bazı T orada olmalı bilir onun tipinde bir joker ile bir değişken karşılaştığında

Transform<? extends BaseA, B> t = (Transform<? extends BaseA, B>) _map.get(b.getClass()); 
+0

nasıl Bu soruya cevap vermez için yararlı olabilir? Bu bir yorum olmalı. –

+0

Aslında bunu yapmaya çalışmıyorum, çünkü Transform'in somut uygulaması argümanın sınıfı tarafından belirlenir, örn. Tamsayı'yı Uzun Bekleyen bir şeye geçmem. – egelev

+0

"Transform t = ..." uzantısını yazar. "" BaseB'yi uzatır "terimi, BaseB'nin herhangi bir alt tipi olabileceği anlamına gelir. Bu DerB, FooB, LambdaB, vb olabilir ... sonra derleyici bakış açısından herhangi bir Transformer <..., DerB>, Trafo <..., FooB>, vb – ursa

0

T türünün neyi temsil ettiğini bilmez, ancak bu tür için T'nin olması gereken türden bir yer tutucu oluşturabilir. Bu yer tutucuya söz konusu joker karakterin yakalanması denir.

Derleyicinin neden capture<? extends BaseB>'un capture<?> extends BaseB olabileceğini anlayamıyorum, tip silmeyle ilgili bir şey olabilir mi?

yerine böyle uygulamak olacaktır:

interface BaseA {} 
interface BaseB {} 
class DerA implements BaseA {} 
class DerB implements BaseB {} 

interface Transform { 
    BaseA toA(BaseB b); 
} 

class DerAtoDerB implements Transform { 
    public BaseA toA(BaseB b) { return new DerA(); } 
} 

class Transformations { 
    private static Map<Class<?>, Transform> _map = 
      new HashMap<>(); 

    static { 
     _map.put(DerB.class, new DerAtoDerB()); 
    } 

    public static<B extends BaseB> BaseA transform(B b) { 
     Transform t = _map.get(b.getClass()); 
     return t.toA(b); 
    } 
} 
+1

Ham türleri jeneriklerle karıştırmayın. Temiz bir çözüm olmalı. :) –

0

?, bilinmeyen tür anlamına gelir.

bir değişken türü X ait olduğunda bunu tip X veya X ancak her alt tipte bir değer atayabilirsiniz "? extends X" başka bir şey anlamına gelir.

Bu x veya x arasında herhangi bir alt türünü olabilir bilinmeyen tip olduğu anlamına gelir. Aynı şey değil.

Örnek: Örneğin t herhangi BaseB ya da ne itiraf ama öyle değil nerede bir örnek gösterilen eğer derleyici bilmez ise

public static Transform<? extends BaseA, ? extends BaseB> getSomething(){ 
    // My custom method 
    return new Transform<MySubclassOfA, MySubclassOfB>(); // <-- It does not accept BaseB, only MySubclassOfB 
} 
public static BaseA transform(BaseB b){ 
    Transform<? extends BaseA, ? extends BaseB> t = getSomething(); 
    return t.toA(b); // <--- THIS IS WRONG, it cannot accept any BaseB, only MySubclassOfB 
} 

.

0

Bu şey derler:

package com.test; 

import java.util.HashMap; 
import java.util.Map; 

interface BaseA{} 
interface BaseB{} 
class DerA implements BaseA{} 
class DerB implements BaseB{} 

interface Transform<A,B> { 
    A toA (B b); 
} 

class DerAtoDerB implements Transform<BaseA,BaseB> { 
    public DerA toA(DerB b){ return null; } 

    @Override 
    public BaseA toA(BaseB baseB) { 
     return null; 
    } 
} 

public class Transformations { 
    private static Map<Class<?>, Transform<? extends BaseA, ? super BaseB>> _map = new HashMap<Class<?>, Transform<? extends BaseA, ? super BaseB>>(); 
    static { 
     _map.put(DerB.class, new DerAtoDerB()); 
    } 

    public static <B extends BaseB> BaseA transform(B b){ 
     Transform<? extends BaseA, ? super BaseB> t = _map.get(b.getClass()); 
     return t.toA(b); 
    } 
} 

Kuralların yapılan değişiklikleri şunlardır:

  1. DerAtoDerB şimdi Transform<BaseA,BaseB> uygular, yerine Map ikinci jenerik parametrenin Transform<DerA,DerB>
  2. Türü Transform<? extends BaseA, ? super BaseB> olarak değiştirildi -yerine super kullanımına dikkat edin- karşı cinsi bağlı.
2

sorun transform yöntemde derleyici tür parametresi B extends BaseB ve harita kazanılmış olan Transform sınıfı (? extends BaseB) 'de ikinci tür parametresinin aynı alt sınıfı temsil bilmiyor olmasıdır BaseB. Eğer doğru katmana döküm yoluyla derleyici söylemek gerekir, böylece

_map.put(DerB.class, new AnotherDerAtoAnotherDerB()); // the types don't match 

Sen haritası maçında olduğu türlerini garanti biridir: Hiçbir şey haritasında uyumsuz bir tip depolama alıkoyar türü:

@SuppressWarnings("unchecked") 
public static <B extends BaseB> BaseA transform(B b) { 
    Transform<? extends BaseA, B> t = 
    (Transform<? extends BaseA, B>)_map.get(b.getClass()); 
    return t.toA(b); 
} 
İlgili konular