163

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.

daniel kullmann
  • 13,653
  • 8
  • 51
  • 67
  • 3
    possible duplicate of [Why are we not allowed to specify a constructor in an interface?](http://stackoverflow.com/questions/689474/why-are-we-not-allowed-to-specify-a-constructor-in-an-interface) – matt b May 10 '10 at 15:42
  • 3
    You say "In the constructor I could ensure [every implementation of this class really has an receiver set]." But no, you couldn't possibly do that. Provided it was possible to define such a constructor, the parameter would only be a strong hint to your implementors – but they could chose to simply ignore it if they wanted to. – Julien Silland May 11 '10 at 03:08
  • 5
    @mattb Umm, that's a different language. – yesennes Jan 23 '16 at 20:21
  • If you want to ensure a class has a certain constructor `B` for some functional purpose `P`, consider requiring that `P` receives the `B` as a parameter somewhere. That way, depending on how you declare it, (`Supplier`, `BiFunction`...), you can guarantee behavior. For an example take a look at [this solution](https://stackoverflow.com/a/71932401/5943840). – Raphael Apr 19 '22 at 23:23

11 Answers11

135

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 classes are for.

zb226
  • 9,586
  • 6
  • 49
  • 79
matt b
  • 138,234
  • 66
  • 282
  • 345
  • but note that the use case @Sebi describes (calling overloaded methods from parent constructors) is a bad idea as explained in my answer. – rsp May 10 '10 at 15:57
  • 46
    Matt, that's clearly true, but abstract classes suffer from the single-inheritance limitation, which leads people to look at other ways of specifying hierarchies. – CPerkins May 10 '10 at 16:09
  • 6
    This is true and may solve Sebi's immediate problem. But one reason for using interfaces in Java is because you cannot have multiple inheritance. In a case where I cannot make my "thing" an abstract class because I need to inherit from something else, the problem remains. Not that I claim to have a solution. – Jay May 10 '10 at 16:10
  • 8
    @CPerkins while this is true, I am not suggesting that simply using an abstract class will solve Sebi's use case. If anything, it's best to declare a `Message` interface which defines the `send()` method, and if Sebi wishes to provide a "base" class for implementations of the `Message` interface, then provide an `AbstractMessage` as well. Abstract classes shouldn't take the place of interfaces, was never attempting to suggest so. – matt b May 10 '10 at 16:17
  • 2
    Understood, Matt. I wasn't arguing with you, more pointing out that it's not a *complete* replacement for what the op wants. – CPerkins May 10 '10 at 20:04
  • Works for me. Essentially you can have the interface and accompanying abstract class. If you are already extending a class, then use the interface. If you are are not extending a class then you can extend the abstract class instead and make use of its constructor. – Jose Martinez Sep 19 '15 at 14:00
83

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); 
  }
}
daniel kullmann
  • 13,653
  • 8
  • 51
  • 67
  • 1
    Couldn't the language have done it by allowing things like `class A implements Named, HashList { A(){HashList(new list()); Named("name");} }` – mako Sep 10 '13 at 23:19
  • 2
    The most useful meaning for a "constructor in an interface", if allowed, would be if `new Set()` could be interpreted to mean "Give me something I can use as a `Set`"; if the author of `Set` intended `HashSet` to be the go-to implementation for things that didn't have a particular need for something else, the interface could then define `new Set()` could be considered synonymous with `new HashSet()`. For a class to implement multiple interfaces would not pose any problem, since `new InterfaceName()` would simply construct a class *designated by the interface*. – supercat Feb 10 '14 at 23:45
  • 1
    Counter-argument: your `A(String,List)` constructor could be the designated constructor, and `A(String)` and `A(List)` could be secondary ones that call it. Your code isn't a counter-example, just a poor one. – Ky - Feb 07 '18 at 03:02
  • Why would you call **all** the constructors in an implementation?! Yes, if it implements more Interfaces with ctor, one with a String and one with an int, it needs that two ctors - but either or can be used. If thats not applicable, the class simply doesn't implement both Interface. So what!? (there are other reasons for not having ctor in Interfaces though ). – kai Mar 22 '19 at 12:52
  • @kai No, it needs to call both interface constructors when constructing an instance. In other words: In my example, the instance has both a name and a list, so each instance needs to instantiate both the name and the list. – daniel kullmann Apr 08 '19 at 15:59
  • now I understand. more a class what you have in mind. right! – kai Apr 08 '19 at 16:04
12

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.

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:

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 after the constructor of the base class.

rsp
  • 23,135
  • 6
  • 55
  • 69
6

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.

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

E.g.

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

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

Satyajit Gami
  • 51
  • 1
  • 1
4

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:

interface IMyMessage(){
    @NonNull String getReceiver();
}
  • it won't break encapsulation
  • it will let know to everyone who use your interface that the Receiver object has to be passed to the class in some way (either by constructor or by setter)
Denys Vasylenko
  • 2,135
  • 18
  • 20
1

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.

NoNaMe
  • 6,020
  • 30
  • 82
  • 110
Aasif Ali
  • 11
  • 3
1

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.

Yishai
  • 90,445
  • 31
  • 189
  • 263
0

See this question for 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.

Community
  • 1
  • 1
JSBձոգչ
  • 40,684
  • 18
  • 101
  • 169
0

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

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);
}
Tord Larsen
  • 2,670
  • 8
  • 33
  • 76
0

Generally constructors are for initializing non-static members of particular class with respect to object.

There is no object creation for interface as there is only declared methods but not defined methods. Why we can’t create object to declared methods is-object creation is nothing but allocating some memory (in heap memory) for non-static members.

JVM will create memory for members which are fully developed and ready to use.Based on those members , JVM calculates how much of memory required for them and creates memory.

Incase of declared methods, JVM is unable to calculate the how much memory will required to these declared methods as the implementation will be in future which is not done by this time. so object creation is not possible for interface.

conclusion:

without object creation, there is no chance to initialize non-static members through a constructor.That is why constructor is not allowed inside a interface.(as there is no use of constructor inside a interface)