2015-11-12 16 views
5

3 arabirim ile başlayalım. Yaptıkları şey önemli değil. Sadece Araba ve parametrelerin(), Foo ve Bar değilken olduğunu unutmayın.Bağlantılı Tip Genel bir Arabirim çalışırken, bir Genel Yöntemdeki Parametreler başarısız oluyor, neden?

interface Foo        {void testFoo();} 
interface Bar        {void testBar();} 
interface Car<A>       {A testCar();} 

ben 'kompozit' Bu arabirimler istiyorum, ve açıkça böyle kompozisyonlar oluşturmayı eğer bu sadece çalışıyor: Ancak

interface FooBar  extends Foo,Bar  {} 
interface FooCar<A>  extends Foo,Car<A> {} 

, ben çok arayüzleri aracılığıyla dolaylı kompozit tercih etmişti Çeşitli yöntemlerin sınırlı tip beyanları.

public <T extends Foo & Bar>  T implicitFooBar() {return null;} 
public <X, T extends Foo & Car<X>> T implicitFooCar() {return null;} 

çalışır: Örneğin:implictFooBar() yöntemi Foo ve Bar arayüzleri (eğer olacak bir kompozit) hem uygulayan bir tip T döndürür. Bu yönteme bir çağrı derler ve açıkça Foobar arayüzü bildirmek zorunda kalmamak için:

// implicit composition of Foo and Bar, GOOD 
FooBar implicitFooBar = implicitFooBar(); 
implicitFooBar.testFoo(); 
implicitFooBar.testBar(); 

başarısız: Bununla birlikte, bir çağrı implicitFooCar() derlenmeyecektir için. Hata mesajı (Ben GenericsTest adlı bir sınıfta benim test kodu tamamladı.)

// implicit composition of Foo and Car<X>, FAIL! 
//Compiler says "The method implicitFooCar() in the type GenericsTest is not applicable for the arguments()" 
FooCar<Number> implicitFooCar = implicitFooCar(); //compile error on method call 
implicitFooCar.testFoo();       
Number n2 = implicitFooCar.testCar(); 

derleyici hata yalnızca gösterileri "tipi GenericsTest yöntem implicitFooCar() argüman() için geçerli değildir" dır tip beyanı hem bileşik hem de parametreli olduğunda. Örneğin, bunlardan ikisi derlemek ve sadece iyi çağrılabilir:

public <X>      Car<X> justCar()  {return null;} 
public <X, T extends Car<X>> T  implicitCar() {return null;} 

Soru ...

bu tip silme ile bir ilgisi vardır şüpheli ama detaylarını anlamak istiyorum Burada neler oluyor. Oracle Generics Tutorials'ı okudum, ancak implicitFooBar() ve implicitCar() yöntemleri iyi iken implicitFooCar() yönteminin hangi kural birleşimini ihlal ettiğini göremiyorum. Sadece bir çalışma değil, akademik bir açıklama arıyorum. İlginçtir ki Bonus

, implicitFooCar() yöntemi (hiçbir derleyici hataları.) Çalışır Bu, diğer sürüm çalışmıyor neden ima, ancak bu noktaları birleştirmek için henüz ettik çağırarak aşağıdaki varyantı .

//variant... GOOD... but why? 
implicitFooCar = this.<Number,FooCar<Number>>implicitFooCar(); 

Testi Kodu (bütün)

kod ile oynamak istiyorsanız

, burada tek bir sınıf olarak olduğunu.

public class GenericsTest { 

    public static interface Foo        {void testFoo();} 
    public static interface Bar        {void testBar();} 
    public static interface Car<A>       {A testCar();} 

    public static interface FooBar  extends Foo,Bar  {} 
    public static interface FooCar<A> extends Foo,Car<A> {} 



    public <X>       Car<X>  justCar()   {return null;} 

    public        FooBar  explicitFooBar() {return null;} 
    public <T extends Foo & Bar>  T   implicitFooBar() {return null;} 

    public <X>       FooCar<X> explicitFooCar() {return null;} 
    public <X, T extends Foo & Car<X>> T   implicitFooCar() {return null;} 

    public <X, T extends Car<X>>  T   implicitCar()  {return null;} 


    public void test() { 
     justCar().testCar(); 

     // explicit composition of Foo and Bar, GOOD 
     FooBar explicitFooBar = explicitFooBar(); 
     explicitFooBar.testFoo(); 
     explicitFooBar.testBar(); 

     // explicit composition of Foo and Car<X>, GOOD 
     FooCar<Number> explicitFooCar = explicitFooCar(); 
     explicitFooCar.testFoo(); 
     Number n1 = explicitFooCar.testCar(); 

     // implicit composition of Foo and Bar, GOOD 
     FooBar implicitFooBar = implicitFooBar(); 
     implicitFooBar.testFoo(); 
     implicitFooBar.testBar(); 

     // implicit composition of Foo and Car<X>, FAIL! 
     //Compiler says "The method implicitFooCar() in the type GenericsTest is not applicable for the arguments()" 
     FooCar<Number> implicitFooCar = implicitFooCar(); //compile error on method call 
     implicitFooCar.testFoo();       
     Number n2 = implicitFooCar.testCar(); 
     //variant... GOOD... but why? 
     implicitFooCar = this.<Number,FooCar<Number>>implicitFooCar(); 

     // implicit (no composition) Car<X>, GOOD 
     Car<Number> implicitCar = implicitCar(); 
     Number n3 = implicitCar.testCar(); 

    } 

} 

GÜNCELLEME

Bu Javac sürümü 1.8.0_60 (ve yorumlar başına _45) ile derler, ama derleyici AAD inşa Eclipse'nın (sürüm 4.4.2.M20150204-1700) Yukarıda belirtilen hata bildiriyor. Bu soruya bir EJC sorunu olabileceğinden bir tutuklama etiketi ekledim.

+1

Alttaki kod örneğiniz benim için derler (Java 1.8.0_45). Java sürümünüz nedir? – rgettman

+1

Ne yapmaya çalıştığını görüyorum ama işe yaramayacak. Özellikle, 'implicitFooBar' için yazdığınız imza, 'Foo' ve 'Bar''ı uygulayan herhangi bir tür için bu türden geri dönebileceğini iddia eder. Bu sadece 'null' değerini döndürürseniz çalışır; gerçek bir nesneyi döndürmeye çalışırsanız işe yaramaz. Java'nın tip sistemi yapmaya çalıştığınız şeyi ifade edemez. –

+0

@LouisWasserman Arka plan için ... Akıcı bir API üzerinde çalışıyorum. Açık arabirimler, API sözdizimindeki noktalarda kullanılabilir eylemleri listeler ve sözdiziminde birden çok eylem kümesinin olası olduğu durumlarda örtülü arabirimler gerekir. Şu anda null döndüren uygulama hakkında iyi bir nokta. Uygulamayı kodlamaya başlamamıştım (sadece API spesifikasyonlarını tercüme ediyordum) ve muhtemelen o zaman aradaki ara arayüzlere ihtiyaç duyuyorum. – allenru

cevap

2

İlk olarak, doğrudan soruma cevap vermek için ...Biri parametrelenmiş olan iki arabirimi bir araya getiren, parametrelenmiş bir parametreli bir yöntemi bildirmek mümkündür.

zaman örnekten implicitFooCar() yöntemin, Luna kullanılan Eclipse derleyici AAD, bir hata Eclipse sürüm 4.4 başarısız oldu. Aynı kod javac derleyici (v 1.8.0_60) ve Eclipse, Mars'ın (4.5) bir sonraki sürümü kullanılarak derlenmiştir. İkincisi, geçici veya ara bileşik arayüzler olarak düşündüğümün açık beyanlarından kaçınmaya olan isteğim kısa görüşlüydi. Louis Wasserman pointed out yönteminin bir noktada bu kompozit spesifikasyona uyan bir nesneyi döndürmesi gerektiğini ve bu noktada açık bir versiyona ihtiyacım olacağını.

İlgili konular