首页 文章

接口中的构造函数?

提问于
浏览
127

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

因此,您可以确保为此接口的每个实现定义了类中的某些字段 .

例如,考虑以下消息类:

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
   }
}

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

11 回答

  • 1

    采取你所描述的一些事情:

    “因此,您可以确定类中的某些字段是为此接口的每个实现定义的 . ” “如果为这个类定义一个接口,以便我可以有更多的类来实现消息接口,那么我只能定义send方法而不是构造函数”

    ......这些要求正是abstract classes的用途 .

  • 1

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

    或者在代码中:

    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); 
      }
    }
    
  • 119

    接口定义API的 Contract ,API是API的实现者和用户都同意的一组方法 . 接口没有实例化实现,因此没有构造函数 .

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

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

    总结一下:当你从父构造函数调用重载方法时引用麻烦,引用mindprod

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

  • 1

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

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

  • 10

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

  • 2

    您可以尝试在界面中定义 getInstance() 方法,以便实施者知道需要处理哪些参数 . 它不像抽象类那样坚固,但它作为一个接口允许更多的灵活性 .

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

    例如 .

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

    请参阅this question了解原因(摘自评论) .

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

  • 0

    这是因为接口不允许在其中定义方法体 . 但是我们必须在接口具有相同类的构造函数中默认使用abstract modifier来定义所有方法 . 这就是我们无法在接口中定义构造函数的原因 .

  • 2

    如果要确保接口的每个实现都包含特定字段,您只需 need to add to your interface the getter for that field

    interface IMyMessage(){
        @NonNull String getReceiver();
    }
    
    • 它不会破坏封装

    • 它会让所有使用你的界面的人知道 Receiver 对象必须以某种方式传递给类(通过构造函数或由setter)

  • 64

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

    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);
    }
    
  • 0

    通常,构造函数用于初始化关于对象的特定类的非静态成员 .

    接口没有对象创建,因为只有声明的方法但没有定义的方法 . 为什么我们不能为声明的方法创建对象is-object的创建只不过是为非静态成员分配一些内存(在堆内存中) .

    JVM将为完全开发并可以使用的成员创建内存 . 基于这些成员,JVM计算它们所需的内存量并创建内存 .

    由于声明的方法很少,JVM无法计算这些声明的方法需要多少内存,因为将来实现将是这种情况 . 所以对象不可能创建对象 .

    结论:

    没有对象创建,就没有机会通过构造函数初始化非静态成员 . 这就是为什么构造函数不允许在接口内部 . (因为在接口中没有使用构造函数)

相关问题