簡體   English   中英

為什么接口不能有字段?

[英]Why can't an interface have fields?

忽略所有內容直到第二次編輯

我正在嘗試做這樣的事情:

public interface IModifier{
   public String nameTag;
   public void foo();
}

我嘗試這樣做的原因是:我有一個類 SpecificModifier 實現了 IModifier,並且有許多非常相似的類也實現了 IModifier。 我希望每個實現 IModifier 的類都有一個公共字符串 nameTag。

編輯:我已經確認我不能這樣做,但是有人可以解釋為什么接口不能需要字段嗎?

編輯二:

我對抽象類與接口的目的的理解。 接口純粹用於聲明實現它的任何內容的必要部分,以便所有對象都有可以引用的公共部分。 而抽象類用於為多個類提供通用功能。

這有點過於簡單化了,但無論如何,除了語言設計者的疏忽之外,我仍然沒有理由認為接口不能具有抽象字段。

任何人都可以提供一個原因嗎?

接口指定一個契約,實現該接口的具體類必須遵守該契約。 這個契約描述了一個實現應該如何行動。 在接口規范中,應該有明確的注釋來描述每個方法的目的是什么。 接口的使用將契約與實際實現分離。 字段是一個實現細節,因為字段不描述類應該如何“充當”。

例如,接口通常用作聲明類型,而具體實現用作實際類型。

    Map<Key,Value> m = new HashMap<>();

考慮一下 java.util.Map 接口。 它通過一組方法描述了 Map 應該如何操作。 Map 接口有幾種不同的實現,允許用戶根據自己的需要選擇正確的實現。

指定一個字段必須由多個子類使用意味着存在某種類層次結構。 在這種情況下,抽象類可以解決問題。

   abstract class IModParent implements IModifier{
      protected String nameTag;
   }

現在你可以有一個具體的類。

   class SpecificModifier extends IModParent{

      SpecificModifier(String nameTag){ this.nameTag = nameTag; }

      @Override
      public void foo(){ System.out.println(nameTag); }
   }

和宣言。

    IModifier imod = new SpecificModifier("MyName");

這使您可以靈活地使用接口類型,同時仍然能夠通過不可實例化的抽象類在所需的具體類組之間共享實現細節。

不,你不能悲傷。 java中的接口只能包含方法和常量。 但是,有一個替代方案。 添加一個這樣的方法:

String getNameTag();

看? 那樣的話,實現必須包含一個nameTag字段,或者他們可以做一些其他的事情來返回一個字符串。

此外,據我所知,您不需要為接口方法添加訪問修飾符。

接口是為方法和常量創建的。

您需要根據您的要求使用abstract class

public abstract class IModifier{
   public String nameTag;
   public abstract void foo();
}

現在回答您的問題WHY an interface cannot require a field? Ans:因為那是abstract class的特性。 interfaceabstract class之間幾乎沒有區別。

我希望我回答了你棘手的問題。

從設計的角度來看:接口定義了一個約定行為的契約,它是可以做的,也就是方法。 (例如 int getAge() )和更少的方法。 然后是實例字段(int age),它們更多地是您實現行為所需的部分並不自然適合。 並且非實現特定的靜態最終字段(例如靜態最終 int CENTURIONAGE=100)在接口上仍然可用。

然后在同意契約之后,如果你去行為實現,你就會去類和抽象類等。

不。

接口只能需要方法,不能需要字段(或構造函數)。

您可以通過在接口中放置 getter 和/或 setter 方法來實現相同的效果。

如果您查找 java 文檔,您將從那里獲得實際的語句。

抽象類類似於接口。 您不能實例化它們,它們可能包含聲明有或沒有實現的混合方法。 但是,使用抽象類,您可以聲明非靜態和最終的字段,並定義公共、受保護和私有的具體方法。 對於接口,所有字段都自動是 public、static 和 final,並且您聲明或定義的所有方法(作為默認方法)都是 public。 此外,您只能擴展一個類,無論它是否是抽象的,而您可以實現任意數量的接口。

你應該使用哪個,抽象類或接口?

如果以下任何陳述適用於您的情況,請考慮使用抽象類:

  1. 您希望在幾個密切相關的類之間共享代碼。
  2. 您希望擴展抽象類的類具有許多通用方法或字段,或者需要公共以外的訪問修飾符(例如 protected 和 private)。
  3. 您想聲明非靜態或非最終字段。 這使您能夠定義可以訪問和修改它們所屬對象狀態的方法。

如果以下任何陳述適用於您的情況,請考慮使用接口:

1.您期望不相關的類會實現您的接口。 例如,接口 Comparable 和 Cloneable 由許多不相關的類實現。

2.您想指定特定數據類型的行為,但不關心誰實現其行為。

3.你想利用類型的多重繼承。

但是,根據您的問題首次編輯,您可以在界面中定義一個字段,但是有一個警告。 它必須是公開的靜態的最終的 換句話說,只定義常量;)

public interface TimeClient {

public static final String TIME_ZONE = "Europe/Amsterdam";    //Defines a static field     

static public ZoneId getZoneId(String zoneString) {
    try {
        return ZoneId.of(zoneString);
    } catch (DateTimeException e) {
        System.err.println("Invalid time zone: " + zoneString
                + "; using default time zone instead.");
        return ZoneId.systemDefault();
    }
}

//Defines a default method
default public ZonedDateTime getZonedDateTime(String zoneString) {
    return ZonedDateTime.of(LocalDateTime.MAX, getZoneId(zoneString));
}}

上面的代碼會編譯。

這是我在許多項目中所做的,以便能夠定義一個“接口”,該“接口”不是定義字段而是定義字段的“合同”。

本主題前面提出的使用abstract基類的建議有一個嚴重的局限性。 一個具體的類可以在 Java 的多重繼承的有限形式中實現多個接口,但是……它只能extend一個基類。 這意味着基類方法僅適用於需要字段約定的接口。

以用例的方式,假設我想要幾種域對象的合同/接口:

  • 具有到期日期的對象
  • 具有審計跟蹤的對象(創建者、創建日期、...)

我可能有可以過期但不需要審計跟蹤的對象。 我可能有其他相反的對象:它們需要審計跟蹤,但沒有到期日期。

基類不允許在其中進行某種“挑選”。 任何基類都必須定義兩者,或者您必須為所有組合都定義基類。

這是我的解決方案,它運行良好:我將 setter 和 getter 定義為接口中的抽象方法。 您將實現留給具體的類。

public interface Auditable<USER_TYPE> {
    Instant getCreatedOn();
    void setCreatedOn(Instant)

    USER_TYPE getCreatedBy();
    void setCreatedBy(USER_TYPE creator);

一個既可審計(使用String來識別用戶)又可過期的具體類看起來像這樣(我正在使用 Lombok)

@Getter @Setter
public AuditableExpirableObject implement Auditable<String>, Expirable {
    private String createdBy
    private Instant createdOn;
    private Instant expirationDate;

這允許具體對象選擇它們使用的接口。 您確實必須定義字段,但在具體類型中定義它們但實現接口契約通常是一件“好事”。 原因的一個例子是允許每個具體類確定以下內容:

  • 數據類型(如Auditable的用戶類型)
  • 持久化或序列化注解(Hibernate、JPA、Jackson、Gson 等)
  • 自定義初始化或保護級別

暫無
暫無

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

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