Constructeur in een interface?

Ik weet dat het niet mogelijk is om een ​​constructor in een interface te definiëren. Maar ik vraag me af waarom, omdat ik denk dat het heel nuttig kan zijn.

Je kunt er dus zeker van zijn dat sommige velden in een klasse zijn gedefinieerd voor elke implementatie van deze interface.

Beschouw bijvoorbeeld de volgende berichtklasse:

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

Als ik een interface voor deze klasse definieer zodat ik meer klassen kan hebben die de berichtinterface implementeren, kan ik alleen de verzendmethode definiëren en niet de constructor. Dus hoe kan ik ervoor zorgen dat elke implementatie van deze klasse echt een ontvangerset heeft? Als ik een methode als setReceiver(String receiver)gebruik, weet ik niet zeker of deze methode echt wordt aangeroepen. In de constructor kon ik ervoor zorgen.


Antwoord 1, autoriteit 100%

Sommige dingen nemen die je hebt beschreven:

“Je kunt er dus zeker van zijn dat sommige velden in een klasse zijn gedefinieerd voor
elke implementatie van deze interface.”

“Als ik een interface voor deze klasse definieer, zodat ik er meer kan hebben
klassen die de berichtinterface implementeren, kan ik alleen de . definiëren
send methode en niet de constructor”

…deze vereisten zijn precies wat abstracte klassenzijn voor.


Antwoord 2, autoriteit 62%

Een probleem dat je krijgt als je constructors in interfaces toestaat, komt van de mogelijkheid om meerdere interfaces tegelijkertijd te implementeren. Wanneer een klasse verschillende interfaces implementeert die verschillende constructors definiëren, zou de klasse verschillende constructors moeten implementeren, die elk aan slechts één interface voldoen, maar niet aan de andere. Het zal onmogelijk zijn om een ​​object te construeren dat elk van deze constructors aanroept.

Of 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); 
  }
}

Antwoord 3, autoriteit 9%

Een interface definieert een contract voor een API, dat wil zeggen een reeks methoden waarover zowel de uitvoerder als de gebruiker van de API het eens zijn. Een interface heeft geen instantie-implementatie, dus geen constructor.

De use case die je beschrijft is verwant aan een abstracte klasse waarin de constructor een methode aanroept van een abstracte methode die is geïmplementeerd in een onderliggende klasse.

Het inherente probleem hier is dat terwijl de basisconstructor wordt uitgevoerd, het onderliggende object nog niet is geconstrueerd en daarom in een onvoorspelbare staat verkeert.

Samenvattend: is het vragen om problemen als je overbelaste methoden van bovenliggende constructors aanroept, om mindprod te citeren :

Over het algemeen moet u voorkomen dat u iemand belt
niet-finale methoden in een constructor.
Het probleem is dat exemplaar
initialisatie / variabele initialisatie
in de afgeleide klasse wordt uitgevoerd
nade constructor van de basis
klas.


Antwoord 4, autoriteit 5%

Een oplossing die u kunt proberen, is het definiëren van een getInstance()-methode in uw interface, zodat de implementeerder weet welke parameters moeten worden afgehandeld. Het is niet zo solide als een abstracte klasse, maar het biedt meer flexibiliteit als een interface.

Voor deze tijdelijke oplossing moet u echter getInstance()gebruiken om alle objecten van deze interface te instantiëren.

Bijvoorbeeld

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

Antwoord 5, autoriteit 3%

Er zijn alleen statische velden in de interface die niet hoeven te worden geïnitialiseerd tijdens het maken van objecten in de subklasse en de interfacemethode moet daadwerkelijke implementatie bieden in de subklasse. Er is dus geen constructor nodig in de interface.

Tweede reden: tijdens het maken van het object van de subklasse, wordt de bovenliggende constructor aangeroepen. Maar als er meer dan één interface wordt geïmplementeerd, zal er een conflict optreden tijdens het aanroepen van de interface-constructor over welke interface-constructor het eerst zal aanroepen.


Antwoord 6, autoriteit 2%

Als je er zeker van wilt zijn dat elke implementatie van de interface een specifiek veld bevat, moet je gewoon de getter voor dat veld aan je interface toevoegen:

interface IMyMessage(){
    @NonNull String getReceiver();
}
  • het zal de inkapseling niet breken
  • het zal iedereen die uw interface gebruikt laten weten dat het Receiver-object op de een of andere manier aan de klasse moet worden doorgegeven (door de constructor of door de setter)

Antwoord 7

Afhankelijkheden waarnaar niet wordt verwezen in een interfacemethode moeten worden beschouwd als implementatiedetails, niet als iets dat de interface afdwingt. Natuurlijk kunnen er uitzonderingen zijn, maar in de regel moet u uw interface definiëren zoals het gedrag naar verwachting zal zijn. De interne status van een bepaalde implementatie zou geen ontwerpprobleem van de interface moeten zijn.


Antwoord 8

Dit komt omdat interfaces het niet toestaan ​​om de body van de methode erin te definiëren. Maar we zouden de constructor in dezelfde klasse moeten definiëren als interfaces die standaard een abstracte modifier hebben om alle methoden te definiëren. Daarom kunnen we de constructor niet definiëren in de interfaces.


Antwoord 9

Zie deze vraagvoor het waarom(uit de opmerkingen).

Als je zoiets echt moet doen, wil je misschien een abstracte basisklasse in plaats van een interface.


Antwoord 10

Hier is een voorbeeld waarin deze techniek wordt gebruikt. In dit specifieke voorbeeld doet de code een aanroep naar Firebase met behulp van een nep MyCompletionListenerdie een interface is die is gemaskeerd als een abstracte klasse, een interface met een 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);
}

Antwoord 11

Over het algemeen zijn constructors bedoeld voor het initialiseren van niet-statische leden van een bepaalde klasse met betrekking tot het object.

Er is geen objectcreatie voor de interface omdat er alleen gedeclareerde methoden zijn, maar geen gedefinieerde methoden. Waarom we geen object kunnen maken met gedeclareerde methoden is-object creatie is niets anders dan wat geheugen (in heap-geheugen) toewijzen aan niet-statische leden.

JVM zal geheugen voor leden creëren die volledig ontwikkeld en gebruiksklaar zijn. Op basis van die leden berekent JVM hoeveel geheugen er voor hen nodig is en creëert het geheugen.

In het geval van gedeclareerde methoden, kan JVM niet berekenen hoeveel geheugen nodig is voor deze gedeclareerde methoden, aangezien de implementatie in de toekomst zal plaatsvinden, wat tegen die tijd nog niet is voltooid. dus objectcreatie is niet mogelijk voor interface.

conclusie:

zonder objectcreatie is er geen kans om niet-statische leden te initialiseren via een constructor. Daarom is constructor niet toegestaan ​​in een interface.(aangezien er geen constructor wordt gebruikt in een interface)

Other episodes