[英]Why can't an interface have fields?
Ignore everything up until the second edit忽略所有内容直到第二次编辑
I am trying to do something like this:我正在尝试做这样的事情:
public interface IModifier{
public String nameTag;
public void foo();
}
My reason for trying to do this is this: I have a class SpecificModifier implements IModifier and there are many very similar class that also implement IModifier.我尝试这样做的原因是:我有一个类 SpecificModifier 实现了 IModifier,并且有许多非常相似的类也实现了 IModifier。 I want every class that implements IModifier to have a public String nameTag.
我希望每个实现 IModifier 的类都有一个公共字符串 nameTag。
Edit: I have gotten confirmation that I cannot do this, but can someone explain WHY an interface cannot require a field?编辑:我已经确认我不能这样做,但是有人可以解释为什么接口不能需要字段吗?
Edit two:编辑二:
My understand of the purpose of abstract classes vs interfaces.我对抽象类与接口的目的的理解。 An interface is used purely to declare necessary parts of whatever implements it, so that all the objects have common parts that can be referenced.
接口纯粹用于声明实现它的任何内容的必要部分,以便所有对象都有可以引用的公共部分。 While an abstract class is used to provide common functionality to multiple classes.
而抽象类用于为多个类提供通用功能。
That is a little bit of an over simplification but regardless, I still see no reason, other than an oversight by the language designers, that an interface cannot have an abstract field.这有点过于简单化了,但无论如何,除了语言设计者的疏忽之外,我仍然没有理由认为接口不能具有抽象字段。
Can anyone provide a reason why?任何人都可以提供一个原因吗?
An Interface specifies a contract, which a concrete class that implements the Interface must adhere to.接口指定一个契约,实现该接口的具体类必须遵守该契约。 This contract describes how an implementation should act.
这个契约描述了一个实现应该如何行动。 In the Interface specification, there should be clear comments that describe what the purpose of each method is.
在接口规范中,应该有明确的注释来描述每个方法的目的是什么。 The use of an Interface decouples the contract from the actual implementation.
接口的使用将契约与实际实现分离。 Fields are an implementation detail, as fields do not describe how a class should "act as."
字段是一个实现细节,因为字段不描述类应该如何“充当”。
For instance, Interfaces are commonly used as a declared type and a concrete implementation is used as an actual type.例如,接口通常用作声明类型,而具体实现用作实际类型。
Map<Key,Value> m = new HashMap<>();
Consider the java.util.Map Interface for a moment.考虑一下 java.util.Map 接口。 It describes how a Map should act, via its set of methods.
它通过一组方法描述了 Map 应该如何操作。 There are several different implementations of the Map interface that allow users to choose the correct implementation for their needs.
Map 接口有几种不同的实现,允许用户根据自己的需要选择正确的实现。
Specifying that a field must be used by several sub classes implies that there is some semblance of a class hierarchy.指定一个字段必须由多个子类使用意味着存在某种类层次结构。 In this case an abstract class could do the trick.
在这种情况下,抽象类可以解决问题。
abstract class IModParent implements IModifier{
protected String nameTag;
}
Now you can have a concrete class.现在你可以有一个具体的类。
class SpecificModifier extends IModParent{
SpecificModifier(String nameTag){ this.nameTag = nameTag; }
@Override
public void foo(){ System.out.println(nameTag); }
}
And a declaration.和宣言。
IModifier imod = new SpecificModifier("MyName");
This gives you the flexibility of using an Interface type while still being able to share implementation details via a non-instantiable abstract class across the group of concrete classes that you want.这使您可以灵活地使用接口类型,同时仍然能够通过不可实例化的抽象类在所需的具体类组之间共享实现细节。
No, you can't sadly.不,你不能悲伤。 Interfaces in java can only contain methods and constants.
java中的接口只能包含方法和常量。 But , there is an alternative to this.
但是,有一个替代方案。 Add a method like this:
添加一个这样的方法:
String getNameTag();
See?看? that way, the implementations must contain a
nameTag
field, or they can just do some other stuff to return a string.那样的话,实现必须包含一个
nameTag
字段,或者他们可以做一些其他的事情来返回一个字符串。
Also, as far as I know, you don't need to add access modifiers to interface methods.此外,据我所知,您不需要为接口方法添加访问修饰符。
Interface is made for methods and constants.接口是为方法和常量创建的。
You need to use abstract class
as per your requirements.您需要根据您的要求使用
abstract class
。
public abstract class IModifier{
public String nameTag;
public abstract void foo();
}
Now answer to your question WHY an interface cannot require a field?
现在回答您的问题
WHY an interface cannot require a field?
Ans: Because that is the feature of abstract class
. Ans:因为那是
abstract class
的特性。 It would be almost no difference between interface
and abstract class
. interface
和abstract class
之间几乎没有区别。
I hope that I answered your tricky question.我希望我回答了你棘手的问题。
From the perspective of design: Interface defines a contract of agreed behavior which is what can be done aka methods.从设计的角度来看:接口定义了一个约定行为的契约,它是可以做的,也就是方法。 (Eg int getAge() ) and less of how to do it.
(例如 int getAge() )和更少的方法。 Then Instance Fields (int age) which are more in part what u need to achieve the behavior doesnt naturally fit.
然后是实例字段(int age),它们更多地是您实现行为所需的部分并不自然适合。 And Static final fields that are not implementation specific (Eg static final int CENTURIONAGE=100) is still availble on interface.
并且非实现特定的静态最终字段(例如静态最终 int CENTURIONAGE=100)在接口上仍然可用。
Then after agreeing on the contract, if you go to behavior implementation you go on to classess and abstract classes etc.然后在同意契约之后,如果你去行为实现,你就会去类和抽象类等。
No.不。
Interfaces can only require methods, not fields (or constructors).接口只能需要方法,不能需要字段(或构造函数)。
You could probably achieve the same effect by putting a getter and/or setter method in the interface.您可以通过在接口中放置 getter 和/或 setter 方法来实现相同的效果。
If you look up the java docs, you will get the actual statements from there.如果您查找 java 文档,您将从那里获得实际的语句。
Abstract classes are similar to interfaces.抽象类类似于接口。 You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation.
您不能实例化它们,它们可能包含声明有或没有实现的混合方法。 However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods.
但是,使用抽象类,您可以声明非静态和最终的字段,并定义公共、受保护和私有的具体方法。 With interfaces, all fields are automatically public, static, and final, and all methods that you declare or define (as default methods) are public.
对于接口,所有字段都自动是 public、static 和 final,并且您声明或定义的所有方法(作为默认方法)都是 public。 In addition, you can extend only one class, whether or not it is abstract, whereas you can implement any number of interfaces.
此外,您只能扩展一个类,无论它是否是抽象的,而您可以实现任意数量的接口。
Which should you use, abstract classes or interfaces?你应该使用哪个,抽象类或接口?
Consider using abstract classes if any of these statements apply to your situation:如果以下任何陈述适用于您的情况,请考虑使用抽象类:
Consider using interfaces if any of these statements apply to your situation:如果以下任何陈述适用于您的情况,请考虑使用接口:
1.You expect that unrelated classes would implement your interface. 1.您期望不相关的类会实现您的接口。 For example, the interfaces Comparable and Cloneable are implemented by many unrelated classes.
例如,接口 Comparable 和 Cloneable 由许多不相关的类实现。
2.You want to specify the behavior of a particular data type, but not concerned about who implements its behavior. 2.您想指定特定数据类型的行为,但不关心谁实现其行为。
3.You want to take advantage of multiple inheritance of type. 3.你想利用类型的多重继承。
However, based on your question first edit, you could define a field in an interface, however there is a caveat.但是,根据您的问题首次编辑,您可以在界面中定义一个字段,但是有一个警告。 its has to be public , static and final .
它必须是公开的、静态的和最终的。 In other words, define only constants ;)
换句话说,只定义常量;)
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));
}}
The above code will compile.上面的代码会编译。
Here's what I have done in many projects to be able to define an "interface" that defines not fields but a "contract" for fields.这是我在许多项目中所做的,以便能够定义一个“接口”,该“接口”不是定义字段而是定义字段的“合同”。
The suggestion made earlier in this topic to use abstract
base classes has a severe limitation.本主题前面提出的使用
abstract
基类的建议有一个严重的局限性。 A concrete class can implement multiple interfaces in Java's limited form of multiple inheritance, but... it can only extend
one base class.一个具体的类可以在 Java 的多重继承的有限形式中实现多个接口,但是……它只能
extend
一个基类。 That means that the base class method only works for one interface that requires a contract for fields.这意味着基类方法仅适用于需要字段约定的接口。
In the way of a use case, suppose I wanted a contract/interface for several kinds of domain objects:以用例的方式,假设我想要几种域对象的合同/接口:
I may have objects which can expire but don't need audit trails.我可能有可以过期但不需要审计跟踪的对象。 I may have other objects which are the opposite: they need audit trails, but don't have expiration dates.
我可能有其他相反的对象:它们需要审计跟踪,但没有到期日期。
Base classes don't allow for a sorta "pick and choose" among these.基类不允许在其中进行某种“挑选”。 Any base class would have to define both, or you'd have to have base classes for ALL combinations.
任何基类都必须定义两者,或者您必须为所有组合都定义基类。
Here's my solution and it has worked quite well: I define the setters and getters as abstract methods in the interface.这是我的解决方案,它运行良好:我将 setter 和 getter 定义为接口中的抽象方法。 You leave the implementation to the concrete classes.
您将实现留给具体的类。
public interface Auditable<USER_TYPE> {
Instant getCreatedOn();
void setCreatedOn(Instant)
USER_TYPE getCreatedBy();
void setCreatedBy(USER_TYPE creator);
A concrete class that is both Audtiable (using String
to identify a user) and Expirable would look like this (I'm using Lombok)一个既可审计(使用
String
来识别用户)又可过期的具体类看起来像这样(我正在使用 Lombok)
@Getter @Setter
public AuditableExpirableObject implement Auditable<String>, Expirable {
private String createdBy
private Instant createdOn;
private Instant expirationDate;
This allows concrete objects to select which interfaces they use.这允许具体对象选择它们使用的接口。 You do have to DEFINE the fields, but it is often a "good thing" to define them in concrete types but implement the contract of an inteface.
您确实必须定义字段,但在具体类型中定义它们但实现接口契约通常是一件“好事”。 An example of why, would be to allow each concrete class to determine things like:
原因的一个例子是允许每个具体类确定以下内容:
Auditable
)Auditable
的用户类型)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.