【问题标题】:What is the best practice (if al all) to implement an interface and have a common property?实现接口并具有共同属性的最佳实践(如果全部)是什么?
【发布时间】:2021-03-16 16:28:49
【问题描述】:

我实际上要问的是,如果我希望所有实现都具有一个共同的(但不是静态的!)属性,是否有比使用抽象类更好的方法。

例如:

public interface MyInterface{

   public int someProperty = 0;

   public void doSomething();

}

public ClassA implements MyInterface{

   @Override 
   public void doSomething(){...}
}

public ClassB implements MyInterface{

   @Override 
   public void doSomething(){...}
}

有没有办法创建这两个实现的实例并初始化接口的 someProperty 成员?

或者我必须使用抽象类而不是接口来为每个实现实例初始化这个成员?

【问题讨论】:

  • Java 现在允许其接口成员的默认实现。是什么阻止您创建 static 属性?
  • 不要像这样定义公共属性。仅使用接口来定义类型。将公共属性放在不可实例化的类中。
  • @RobertHarvey 该成员静态的(并且是最终的,并且自动公开)。
  • @AndyTurner:“普通但不是static”对我来说感觉像是一个矛盾。

标签: java


【解决方案1】:

Java 中的接口没有成员字段,只有方法。 (讨论here。)换句话说,接口定义行为,但不定义状态。

您可以通过在接口上声明 JavaBeans 样式的访问器方法 get…set… 来暗示属性存在。

如果您想确保每个对象都有自己的具有特定名称的特定类型的成员字段,那么可以,正如您所建议的那样,使用该字段定义一个抽象类。

当然,您可以同时做到这两个:编写一个包含成员字段的抽象类,该成员字段实现需要访问器方法的接口。两者都做是否是个好主意取决于您的具体情况。


以下是一个可能的示例场景,它同时具有 (a) 一个带有成员字段的抽象类,以及 (b) 一个需要 getter/setter 访问器方法的接口。我不完全确定我在这个例子中的逻辑的完整性,但希望它传达了一般的想法。

车辆种类繁多。有些在公共街道上使用是合法的,有些则不是。街头合法的一方面是拥有Vehicle identification number (VIN)

让我们定义车辆的层次结构。

  • Vehicle 是祖父超类,是抽象的。
  • GoKartVehicle 的一个子类,也是抽象的,在街上开车是不合法的。
  • Vin 是代表我们车辆识别号 (VIN) 类型的记录。
  • CarVehicle 的另一个子类,也是抽象的。但是汽车在街上行驶是合法的。这个抽象类带有一个protected 类型的Vin 类成员,由任何子类继承。
  • 为了将Car 类及其子类标记为合法,我们定义了一个StreetLegal 接口。该接口定义了一对方法来暗示属性Vin 存在于所有实现该方法的类中。
  • 为了将这一切整合在一起,我们为一种特定类型的汽车提供了一个示例具体类 HondaElement
package work.basil.example.cartalk;

public abstract class Vehicle
{
}
package work.basil.example.cartalk;

// Not street-legal.
// https://en.wikipedia.org/wiki/Go-kart
public abstract class GoKart extends Vehicle
{
    public boolean hasRemoteSpeedControl ;
}
package work.basil.example.cartalk;

// VIN = Vehicle identification number.
// https://en.wikipedia.org/wiki/Vehicle_identification_number#North_American_check_digits
public record Vin(String countryCode, int checkDigit, String serialNumber)
{
    // Add constructor to validate data.
}
package work.basil.example.cartalk;

public abstract class Car extends Vehicle implements StreetLegal
{
    protected Vin vin ;
}
package work.basil.example.cartalk;

public interface StreetLegal
{
    public Vin getVin ( );

    public void setVin ( Vin vin );
}
package work.basil.example.cartalk;

public class HondaElement extends Car implements StreetLegal
{
    public HondaElement ( Vin vin )
    {
        this.vin = vin;   // Accessing member field defined on abstract superclass `Car`.
    }

    @Override
    public Vin getVin ( )
    {
        return this.vin;  // Accessing member field defined on abstract superclass `Car`.
    }

    @Override
    public void setVin ( Vin vin )
    {
        this.vin = vin;   // Accessing member field defined on abstract superclass `Car`.
    }
}

【讨论】:

  • @ArvindKumarAvinash 虽然我同意 Stack Overflow 上不断恶化的情况,但公平地说,这个问题不是一个合适的例子。正如最初所写的那样,对于“公共属性”的措辞是指跨实例共享的单个值还是每个实例都有自己的值的成员字段,存在一些歧义。这种歧义可能会证明基于需要细节/清晰性而投票结束的合理性,尽管询问在评论中也可能是合适的。Mark Rotteveel 很快进行了编辑以澄清问题;现在比原来的条件有了很大改进。
猜你喜欢
  • 2010-10-30
  • 2010-09-12
  • 1970-01-01
  • 2011-03-17
  • 2018-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-17
相关资源
最近更新 更多