Java 接口中的构造函数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2804041/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 13:00:59  来源:igfitidea点击:

Constructor in an Interface?

javainterface

提问by

I know it's not possible to define a constructor in an interface. But I'm wondering why, because I think it could be very useful.

我知道不可能在接口中定义构造函数。但我想知道为什么,因为我认为它可能非常有用。

So you could be sure that some fields in a class are defined for every implementation of this interface.

因此,您可以确定类中的某些字段是为该接口的每个实现定义的。

For example consider the following message class:

例如,考虑以下消息类:

public class MyMessage {

   public MyMessage(String receiver) {
      this.receiver = receiver;
   }

   private String receiver;

   public void send() {
      //some implementation for sending the mssage to the receiver
   }
}

If a define an interface for this class so that I can have more classes which implement the message interface, I can only define the send method and not the constructor. So how can I ensure that every implementation of this class really has an receiver set? If I use a method like setReceiver(String receiver)I can't be sure that this method is really called. In the constructor I could ensure it.

如果为这个类定义一个接口以便我可以有更多实现消息接口的类,我只能定义发送方法而不是构造函数。那么我怎样才能确保这个类的每个实现真的有一个接收器集呢?如果我使用像setReceiver(String receiver)我不能确定这个方法真的被调用的方法。在构造函数中,我可以确保它。

采纳答案by matt b

Taking some of the things you have described:

拿你所描述的一些事情:

"So you could be sure that some fields in a class are defined for every implementation of this interface."

"If a define a Interface for this class so that I can have more classes which implement the message interface, I can only define the send method and not the constructor"

“所以你可以确定一个类中的某些字段是为这个接口的每个实现定义的。”

“如果为这个类定义一个接口以便我可以有更多实现消息接口的类,我只能定义发送方法而不是构造函数”

...these requirements are exactly what abstract classesare for.

...这些要求正是抽象类的用途。

回答by Yishai

Dependencies that are not referenced in an interfaces methods should be regarded as implementation details, not something that the interface enforces. Of course there can be exceptions, but as a rule, you should define your interface as what the behavior is expected to be. Internal state of a given implementation shouldn't be a design concern of the interface.

接口方法中未引用的依赖项应视为实现细节,而不是接口强制执行的内容。当然也可能有例外,但作为一项规则,您应该将接口定义为预期的行为。给定实现的内部状态不应该是接口的设计问题。

回答by JSB????

See this questionfor the why(taken from the comments).

请参阅此问题以了解原因(取自评论)。

If you really need to do something like this, you may want an abstract base class rather than an interface.

如果你真的需要做这样的事情,你可能需要一个抽象基类而不是一个接口。

回答by rsp

An interface defines a contract for an API, that is a set of methods that both implementer and user of the API agree upon. An interface does not have an instanced implementation, hence no constructor.

接口定义了 API 的契约,即 API 的实现者和用户都同意的一组方法。接口没有实例化的实现,因此没有构造函数。

The use case you describe is akin to an abstract class in which the constructor calls a method of an abstract method which is implemented in an child class.

您描述的用例类似于抽象类,其中构造函数调用在子类中实现的抽象方法的方法。

The inherent problem here is that while the base constructor is being executed, the child object is not constructed yet, and therfore in an unpredictable state.

这里的固有问题是,在执行基构造函数时,子对象尚未构造,因此处于不可预测的状态。

To summarize: is it asking for trouble when you call overloaded methods from parent constructors, to quote mindprod:

总结一下:当您从父构造函数调用重载方法时,它是否自找麻烦,引用mindprod

In general you must avoid calling any non-final methods in a constructor. The problem is that instance initialisers / variable initialisation in the derived class is performed afterthe constructor of the base class.

通常,您必须避免在构造函数中调用任何非 final 方法。问题是派生类中的实例初始化器/变量初始化是在基类的构造函数之后执行 的。

回答by daniel kullmann

A problem that you get when you allow constructors in interfaces comes from the possibility to implement several interfaces at the same time. When a class implements several interfaces that define different constructors, the class would have to implement several constructors, each one satisfying only one interface, but not the others. It will be impossible to construct an object that calls each of these constructors.

当您允许接口中的构造函数时,您遇到的问题来自同时实现多个接口的可能性。当一个类实现了多个定义不同构造函数的接口时,该类就必须实现多个构造函数,每个构造函数只满足一个接口,而不满足其他接口。不可能构造一个调用这些构造函数中的每一个的对象。

Or in code:

或者在代码中:

interface Named { Named(String name); }
interface HasList { HasList(List list); }

class A implements Named, HasList {

  /** implements Named constructor.
   * This constructor should not be used from outside, 
   * because List parameter is missing
   */
  public A(String name)  { 
    ...
  }

  /** implements HasList constructor.
   * This constructor should not be used from outside, 
   * because String parameter is missing
   */
  public A(List list) {
    ...
  }

  /** This is the constructor that we would actually 
   * need to satisfy both interfaces at the same time
   */ 
  public A(String name, List list) {
    this(name);
    // the next line is illegal; you can only call one other super constructor
    this(list); 
  }
}

回答by Aasif Ali

This is because interfaces do not allow to define the method body in it.but we should have to define the constructor in the same class as interfaces have by default abstract modifier for all the methods to define. That's why we can not define constructor in the interfaces.

这是因为接口不允许在其中定义方法体。但是我们应该在同一个类中定义构造函数,因为接口默认为所有要定义的方法具有抽象修饰符。这就是为什么我们不能在接口中定义构造函数的原因。

回答by Satyajit Gami

There is only static fields in interface that dosen't need to initialized during object creation in subclass and the method of interface has to provide actual implementation in subclass .So there is no need of constructor in interface.

接口中只有静态字段不需要在子类中创建对象时初始化,接口的方法必须在子类中提供实际实现。因此接口中不需要构造函数。

Second reason-during the object creation of subclass, the parent constructor is called .But if there will be more than one interface implemented then a conflict will occur during call of interface constructor as to which interface's constructor will call first

第二个原因——在子类的对象创建过程中,调用了父构造函数。但是如果实现了多个接口,那么在调用接口构造函数时会发生冲突,即首先调用哪个接口的构造函数

回答by ExocetKid

Here′s an example using this Technic. In this specifik example the code is making a call to Firebase using a mock MyCompletionListenerthat is an interface masked as an abstract class, an interface with a constructor

这是使用此技术的示例。在此特定示例中,代码使用模拟调用 Firebase,该模拟MyCompletionListener是一个屏蔽为抽象类的接口,一个带有构造函数的接口

private interface Listener {
    void onComplete(databaseError, databaseReference);
}

public abstract class MyCompletionListener implements Listener{
    String id;
    String name;
    public MyCompletionListener(String id, String name) {
        this.id = id;
        this.name = name;
    }
}

private void removeUserPresenceOnCurrentItem() {
    mFirebase.removeValue(child("some_key"), new MyCompletionListener(UUID.randomUUID().toString(), "removeUserPresenceOnCurrentItem") {
        @Override
        public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {

        }
    });
    }
}

@Override
public void removeValue(DatabaseReference ref, final MyCompletionListener var1) {
    CompletionListener cListener = new CompletionListener() {
                @Override
                public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
                    if (var1 != null){
                        System.out.println("Im back and my id is: " var1.is + " and my name is: " var1.name);
                        var1.onComplete(databaseError, databaseReference);
                    }
                }
            };
    ref.removeValue(cListener);
}

回答by Denys Vasylenko

If you want to make sure that every implementation of the interface contains specific field, you simply need to add to your interface the getter for that field:

如果你想确保接口的每个实现都包含特定的字段,你只需要将那个字段的 getter 添加到你的接口中

interface IMyMessage(){
    @NonNull String getReceiver();
}
  • it won't break encapsulation
  • it will let know to everyone who use your interface that the Receiverobject has to be passed to the class in some way (either by constructor or by setter)
  • 它不会破坏封装
  • 它会让使用你的接口的每个人都知道Receiver对象必须以某种方式传递给类(通过构造函数或通过 setter)

回答by Lappro

A work around you can try is defining a getInstance()method in your interface so the implementer is aware of what parameters need to be handled. It isn't as solid as an abstract class, but it allows more flexibility as being an interface.

您可以尝试的一种解决getInstance()方法是在您的接口中定义一个方法,以便实现者知道需要处理哪些参数。它不像抽象类那样可靠,但它作为接口具有更大的灵活性。

However this workaround does require you to use the getInstance()to instantiate all objects of this interface.

但是,此解决方法确实需要您使用getInstance()来实例化此接口的所有对象。

E.g.

例如

public interface Module {
    Module getInstance(Receiver receiver);
}