簡體   English   中英

為什么不將此類視為超類型作為參數?

[英]Why is this class not considered a supertype as a parameter?

給定以下示例,為什么我可以覆蓋返回類型List<? extends IConfigUser> List<? extends IConfigUser>getUserList() List<ConfigUser> ,但不能對setUserList()的參數進行相同的設置嗎?

在這種情況下, IConfigUser是否不ConfigUser視為ConfigUser的超類型?

public class Test {
   public interface IConfigUser {
   }

   public interface IConfig {
      public List<? extends IConfigUser> getUserList();
      public void setUserList(List<? extends IConfigUser> list);
   }


   public class ConfigUser implements IConfigUser {
   }

   // The type Test.Config must implement the inherited abstract method
   // Test.IConfig.setUserList(List<? extends Test.IConfigUser>)
   public class Config implements IConfig {
      @Override
      public List<ConfigUser> getUserList() {
         return null;
      }

      // The method setUserList(List<ConfigUser> list) of type Test.Config
      // must override or implement a supertype method
      @Override
      public void setUserList(List<ConfigUser> list)
      {
      }
   }
}

您可以通過向IConfig添加通用類型參數來實現您的目標:

public class Test {
   public interface IConfigUser {
   }

   public interface IConfig<T extends IConfigUser> {
      public List<T> getUserList();
      public void setUserList(List<T> list);
   }


   public class ConfigUser implements IConfigUser {
   }

   public class Config implements IConfig<ConfigUser> {
      @Override
      public List<ConfigUser> getUserList() {
         return null;
      }

      @Override
      public void setUserList(List<ConfigUser> list)
      {
      }
   }
}

您可以在覆蓋中返回更具體的類型,但不能要求您接受更具體的類型。 擺脫泛型,可以用返回String的方法重寫返回Object的方法,但是不能用接受String參數的方法重寫接受Object參數的方法。

所有這些都是為了使呼叫者兼容。 考慮:

IConfig config = new Config();    
List<SomeOtherConfigUser> list = new ArrayList<SomeOtherConfigUser>();
list.add(new SomeOtherConfigUser());
config.setUserList(list);

糟糕-您的Config.setUserList期望每個元素都是ConfigUser ,而不是SomeOtherConfigUser

由於協方差,您可以返回(“ specialize”) getUserList() )的返回類型,即,如果您在IConfig引用上調用該方法,那么您將得到List<? extends IConfigUser> List<? extends IConfigUser>List<ConfigUser> List<? extends IConfigUser> List<? extends IConfigUser>以便滿足要求。

如果您在Config參考上調用該信息,則該信息會更具體,但仍滿足基本要求。

使用setUserList(...)的情況有所不同:它允許您傳遞List<? extends IConfigUser> 任何 “子類” List<? extends IConfigUser> List<? extends IConfigUser> ,它可以是 List<ConfigUser>但也可以是其他名稱,例如List<SomeConfigUser>

順便說一句,由於您不知道setUserList(List<ConfigUser> list)list的具體泛型參數,因此編譯器也將只允許您從該列表中讀取內容,而從不添加該列表-出於與上述相同的原因:不知道您得到什么以及是否允許添加ConfigUser ,因為該列表僅允許添加SomeConfigUser實例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM