2010-08-10 14 views
6

Generics'i çok iyi anladığımı sanıyordum ama görünüşe göre yapmadım.Java Generics'te yazım denetleyicisini tamama

import java.util.ArrayList; 

class Job<J extends Job<J,R>, R extends Run<J,R>> {} 
class Run<J extends Job<J,R>, R extends Run<J,R>> {} 

class Job2 extends Job<Job2,Run2> {} 
class Run2 extends Run<Job2,Run2> {} 

class RunList<J extends Job<J,R>, R extends Run<J,R>> extends ArrayList<R> {} 

class Foo { 
    // #1 problem 
    public void test1(RunList<Job,Run> why) {} 
    // #2 this doesn't work either 
    public void test2(RunList<Job<Job,Run>,Run<Job,Run>> why) {} 
    // #3 this works 
    public void test3(RunList<Job2,Run2> why) {} 
} 

derleyici "İş" kendi türü sınırları içinde olmadığını söyleyerek, yukarıda test1 yöntemini izin vermez: Burada

sorunun test niteliği taşıyor. Ben bir tür olarakolarak anlayamıyorum sorta, Job<Job,Run>, dolayısıyla hata uzatmaz. Buna karşılık test3 çalışır.

Şimdi, soru şu, bu işi nasıl yapacağım? # 2 denedim ama bu da işe yaramıyor. Sanırım sorun gerçekten 1 # 0 --- Job<Job,Run> ile benzerdir, çünkü tür argümanı Job ham bir türdür.

Ham tipi kullanmaktan başka, tip denetleyiciyi nasıl mutlu edeceğini bilen var mı? Yoksa Java tipi sistemde elde edilemez mi? Belki

+0

Eğer çalışmak istediğinize herhangi bir ek bilgi verebilir misiniz? Bir çözümünüz var gibi görünüyor - çalışmak istediğiniz hangisi, ve neden? – mlschechter

+0

# 3'ün anlamsal olarak farklı olduğunu ve bir çözüm olmadığını unutmayın; bu bir çözüm değildir. # 3 etkin bir şekilde ArrayList 'u verir ve örneğin oradaki düz Run nesnesini ekleyemezsiniz. RunList'i düz İşler ve Çalışmalar ile istiyorum, böylece örneğin düz bir Run nesnesi koyabilirim. # 2, eğer işe yaradıysa, benzer bir şey elde ederdi. –

cevap

1

: Sonra ArrayList tip parametreyi değiştirirseniz

public <J extends Job<J, R>, R extends Run<J, R>> void test(RunList<J, R> why) {} 
+0

Ama sonra neden yapamıyorum.add (yeni Job()); –

+0

Aksine, why.add (new Run()); –

+0

RunList, R tipi öğelere sahiptir. Bu tür, Çalışmanın bazı alt sınıfıdır. Listeye ekleyebilmeniz için RunList'in çalıştırdığı Run alt sınıfının (veya bunun alt sınıfının) tam alt sınıfını bilmeniz gerekir. Çalıştırmak en iyisi R ile aynıdır ve daha da kötüsü, bir R1 alt tipi ile Diğer perspektiften bakalım, test2'nin şu olabileceğini varsayalım: "why.add (yeni Run());", eğer yazarsanız: RunList rl = yeni RuRunList (); dnm2 (rl); Run2 run2 = rl.get (0); get() satırında bir sınıf döküm istisnası alacaksınız. – nairb774

0

siz) (yeni Çalıştır ekleyebilir;

+0

Jeneriksiz "ArrayList" ham türünü kastediyor musunuz? – whiskeysierra

+0

Ancak bu, RunList'i ham tür olarak kullanmanın daha da kötüsüdür. –

+0

@Willi Daha spesifik olmalıydım. sınıf Çalışma Listesine uzanır R Run uzanır> kullan uzanır ArrayList {} Bu çok Çalıştır Bunu etkileyecek emin değilim tip R. herhangi nesneler nesnelerin yanı sıra eklemek verir RunList sınıfının diğer bölümleri. –

-1

Haklısın, orada ne düşündüğümden emin değilim! Yorumunuz beni daha fazla düşünmeye teşvik etti ve ben bunu test ettim ve sorunun nedeninin Job<J extends Job<J... tip değişkenlerinin özyinelemeli tanımıyla bir ilgisi var, ama neden tamamen açık değilim. Bir çözüm, tanımlarınızdan J ve R 'kullanımını' kaldırın.

Uzun cevap:

import java.util.ArrayList; 

class Job<J extends Job, R extends Run> {} 
class Run<J extends Job, R extends Run> {} 

class Job2 extends Job<Job2,Run2> {} 
class Run2 extends Run<Job2,Run2> {} 

class RunList<J extends Job, R extends Run> extends ArrayList<R> {} 

class Foo { 
    // #1 works now 
    public void test1(RunList<Job,Run> why) {} 
    // #2 works now too 
    public void test2(RunList<Job<Job,Run>,Run<Job,Run>> why) {} 
    // #3 still works 
    public void test3(RunList<Job2,Run2> why) {} 
    // #4 generic method 
    public <J extends Job, R extends Run> void test4(RunList<J,R> why) {} 

    public static void main(String[] args) { 
     // Calling them even works... 
     new Foo().test1(new RunList<Job,Run>()); 
     new Foo().test2(new RunList<Job<Job,Run>,Run<Job,Run>>()); 

     // Calling the generic method works too 
     new Foo().test4(new RunList<Job,Run>()); 
     new Foo().test4(new RunList<Job<Job,Run>,Run<Job,Run>>()); 
     new Foo().test4(new RunList<Job2,Run2>()); 

     // ...sort of 

     // This doesn't work 
     //new Foo().test1(new RunList<Job<Job,Run>,Run<Job,Run>>()); 

     // This doesn't work 
     //new Foo().test1(new RunList<Job2,Run2>()); 

    } 
} 
+0

"Sınırların tip sınırı", sağ taraftaki sınıf/arabirimi içermez; yalnızca alt sınıflarını/alt arayüzlerini içerir ", Üzgünüm, ama yapmadım" öyle düşünmeyin. Listesi, T'yi Sayıyı genişlettiği List 'a atanabilir. –

+0

Kohsuke, jenerik kullanmayı nasıl planlıyorsunuz? Hedefinizin, RunList olduğunuz belirli bir İş alt sınıfıyla uyumlu olduğu bilinen Run alt sınıflarını içerdiğini derleme zamanında zorlama mı? Örneğin, RunList geçerlidir, ancak RunList , Job2 yalnızca Run2 ile çalışmak için yazıldığından değil midir? Ayrıca, İş ve Çalıştır arabirimleri oluşturmada bir sorun var mı? – jaxzin