2016-04-06 8 views
15

parametre olarak Class > iç içe geçen. Ben başarıyla şimdiye kadar derlemek için derleyici aldık: soyut için <code>Retrofit</code> üzerinde benim servis uygulaması bir sarmalayıcı oluşturmak çalışıyorum Android

package com.example.spark.testapp.services; 

import com.example.spark.testapp.services.apis.Get; 
import com.example.spark.testapp.services.apis.Post; 
import com.example.spark.testapp.services.utils.*; 
import com.example.spark.testapp.services.utils.Error; 

import java.util.List; 

import retrofit2.Call; 
import retrofit2.Callback; 
import retrofit2.Response; 
import retrofit2.Retrofit; 




public class ServiceLayer { 
    public <T> void performGet(String url, final Class<Get<T>> clazz, com.example.spark.testapp.services.utils.Callback<T> callback) { 
     Retrofit retrofit = new Retrofit.Builder().baseUrl("").build(); 
     Get<T> service = retrofit.create(clazz); 
     //Pass authentication token here 
     Call<T> t = service.get(url, ""); 
     executeCallback(callback,t); 
    } 

    public <T> void performPost(String url, final Class<Post<T>> clazz,com.example.spark.testapp.services.utils.Callback<T> callback) { 
     Retrofit retrofit = new Retrofit.Builder().baseUrl("").build(); 
     Post<T> service = retrofit.create(clazz); 

     //Pass authentication token here 
     Call<T> t = service.post(url, ""); 
     executeCallback(callback,t); 
    } 

    public <T> void executeCallback(final com.example.spark.testapp.services.utils.Callback<T> callback , Call<T> call) { 
     call.enqueue(new Callback<T>() { 
      @Override 
      public void onResponse(Call<T> call, Response<T> response) { 
       callback.onSuccess(response.body()); 
      } 


      @Override 
      public void onFailure(Call<T> call, Throwable t) { 
       ///Find out what exactly went wrong. Populate Error. and then... 
       com.example.spark.testapp.services.utils.Error e = new Error(); 
       callback.onFailure(e); 
      } 
     }); 
    } 
} 

bu derler iken, sorun yöntemini çağırarak noktasında geçerli:

private void getString() { 

     ServiceLayer s = new ServiceLayer(); 
     s.performGet("",Get<String>.class,this); //Cannot select from parameterised type 

    } 

Bu biraz etrafına Googled ve öğrendim Bu tip silme nedeniyle mümkün değildir. İnce.

Ama soru, derleyici burada bir hata yükseltmek gerekmez mi? Bu hatta mı? :

public <T> void performGet(String url, final Class<Get<T>> clazz, com.example.spark.testapp.services.utils.Callback<T> callback) 

Hizmet katmanım nasıl derlendi?

DÜZENLEME

soru yanlış gibi görünüyor. Bu tasarımın işe yaraması için bir yol aramıyorum. İçindeki kusuru anlıyorum ve hizmetlerimizi katmanlaştırmanın daha iyi bir yolunu bulduk. Soru, dilin kendisinin ilginç/garip davranışlarıyla ilgilidir.

+0

ben 'this' uygular' Geri arama 'varsayıyorum? – njzk2

+0

related: http://stackoverflow.com/questions/27000227/cannot-select-parameterized-type – njzk2

+0

@ njk2 - Evet. Haklısın. Bu, Geri Arama uygular. Ve hiç de alakalı değil. Soru şu ki, sadece çağrı yapamazsanız servis katmanım nasıl derlenir? – avismara

cevap

0

bazı testler yaptım ve umarım yardımcı olacak bazı çözüm buldu.

A<String> a = new A<String>(); 
System.out.println(A.class == a.getClass()); 

Size 'Get < T>' sınıfını almak gerekir ama sadece 'Get anlamına gelir:

bu kod true döndürür yana

(burada bir şey yapmak bazı jenerik sınıftır) 'senin Retrofit için

ne gerek fonksiyon bu T ne olduğunu bilmek için, örneğin, diğer argüman olarak T göndermektir: Eğer jenerik tutmak istiyorsanız

public <T> void performGet(String url, final Class<Get> clazz, final Class<T> t, com.example.spark.testapp.services.utils.Callback<T> callback) { 
    Retrofit retrofit = new Retrofit.Builder().baseUrl("").build(); 
    Get<T> service = retrofit.create(clazz); 
    ... 
+0

Bu çözümü daha önce denedik, ancak 'T'nin tip bilgisinin 'retrofit.create (clazz)' içinde kaybolmasını istemiyoruz. Ne döndürür, "Get" türünü al değil 'tür. – avismara

+0

Türüne göre sınıf mı kastediyorsunuz? Eğer ilk örnek evetse, '' Al ve Get 'in aynı sınıfta olduğunu gösterir. Aksi takdirde, ' = ... 'Get'i ayarladıktan sonra ne tür bir hata yapacağınızı söyleyemez misiniz? –

+0

Yazarak, türünü kastediyorum. Bir hata alamıyorum, ancak bana doğal olarak bir uyarı veriyor. Get 've' Get' türünün türü aynı değildir. Bunu önerdiğin şekilde yapsak bile, derleyecektir, ama yapmak istediğim şeyi yapmak kesinlikle başarısız olacaktır. :) Artı, bu yine de sorumun cevabı değil. – avismara

-1

Bir yöntemde ulaşılabilen sınıf parametresi (T) bilgisi, sınıf bilgisini sağlamanız gerekir. Örnek:

public class SomeClass<T, X, C> { 
    Class<X> xClass; 
    Class<T> tClass; 
    Class<C> cClass; 

    public SomeClass<T, X, C>(Class<T> a, Class<X> b, Class<C> c){ 
     tClass = a; 
     xClass = b; 
     cClass = c; 
    } 
} 

Bu şekilde, "tüketici" sınıf içinde sınıf bilgi kullanabilirsiniz, ya Şimdi vb jenerik yöntemleri çağırmadan,

ortak imzaları, seri/seri kaldırma işlemlerini, nesne oluşturma erişmek için , sadece bir yönteme içinde genel bir sınıf parametrenin bilgi kullanmak istiyorsanız, yapmanız gerekir: Bu, yöntemini içeren sınıfa jenerik sınıf bilgileri kaydedilirken daha aynı tanır

public <T> void performGet(String url, final Class<T> clazz, com.example.spark.testapp.services.utils.Callback<T> callback) { 
    Retrofit retrofit = new Retrofit.Builder().baseUrl("").build(); 
    Get<T> service = retrofit.create(clazz); 
    //Pass authentication token here 
    Call<T> t = service.get(url, ""); 
    executeCallback(callback,t); 
} 

; Eğer yönteme içinde kendisine erişebilir ve bir diğer jenerik yöntemler için parametre ve her şeyin olarak kullanabilirsiniz. Daha fazla örnek gerekirse

, bu bir göz atın. O yüzden belki ondan bazı fikirler alabilirsiniz Spring'in RestTemplate-Android etrafında çok ama etrafında bir sarıcı var. (Feragat - teh dev kulüpler)

https://github.com/fcopardo/EasyRest/blob/master/src/main/java/com/grizzly/rest/GenericRestCall.java

+0

Lütfen düzenlemeye bir göz atın. Bunu işe almak için bir çözüm aramıyorum. Derleyicinin neden bu kodun derlenmesini istediğini soruyorum --- bir yöntem imzasının kalıcılığının olmadığı bir kod --- --- ne zaman olması gerektiği gibi. Bu cevap, olduğu kadar bilgilendirici, gerçekten ne olduğumu değil. aramak – avismara

4

Ama soru, derleyici burada bir hata yükseltmek gerekmez mi?

yöntem imzası

Java mükemmel doğrudur. Ve jenerik yöntem imzaları normal yöntemlerle aynı kurallarla kontrol edilir. genel yöntemde

, kodda yapabileceği eylemler parametre tipleri bağlıdır. Örneğin, bu yöntemi varsa:

public static <T> void test(List<T> list, Class<T> clazz) 
     throws InstantiationException, IllegalAccessException 
{ 
    list.add(clazz.newInstance()); 
} 

Bu derler, ama biz bir sonraki satırı ekleyin:

list.add(new Integer(1)); 

derleme zamanında list sadece T örneklerini kabul olmaz çünkü. Bu nedenle jenerik yöntem iyi tanımlanmıştır.

Eğer jenerik yöntemini çalıştığınızda

, derleyici parametrelerinden T anlaması mümkün değil. Esas sorun, yöntem imzasında geçerli olan ancak önerilmeyen Class<Get<T>> yapısının açık olmasıdır. Güvenli olmayan bir ve tuhaf yöntem çağrısı derlemek yapmak için oyuncu ve işi yapabilir rağmen: Bu döküm zincirini yapmak

s.performGet("",(Class<Get<String>>)(Class) Get.class,this); 

jenerik türleri yalnızca derleme zamanında kontrol edilir çünkü derleyici şimdi, T çıkarabiliriz. Çalışma zamanında, Class<Get<T>> her zaman Get.class olacaktır.

Bu konu hakkında ilgili bazı sorular:

Passing the Class<T> in java of a generic list?

Generic type as parameter in Java Method

1

İlk olarak, sözdizimi derleyici dolayısıyla verilen çizgide dhov hata geçerli değildir olduğunu. Muhtemelen Class ile ilgili olan hata, VM tarafından oluşturulan özel bir sınıftır ve derleyici, hata kontrolü sırasında normal sınıf olarak değerlendirilir. Eğer

ServiceLayer a = new ServiceLayer(); 
    Clazz<Get<String>> clazz = new Clazz<Hello.Get<String>>(); 
    Callback<String> callback = new Callback<String>(); 
    a.performGet("someurl", clazz, callback); 

aramaya çalıştığımda Herhangi bir sorun isterseniz şimdi

class Get<T> { 
    } 

class Callback<T> { 
    } 
class Clazz<T> { 
    } 

static class ServiceLayer { 

     public <T> void performGet(String url, final Clazz<Get<T>> clazz, 
       Callback<T> callback) { 
     } 
    } 

:

bu örneğe bakın. Gördüğünüz gibi, bu sözdiziminde sorun yok, ama özel bir nesne ile.

İlgili konular