een object casten naar een interface in java?

als we een object naar een interface werpen, kan dit object dan zijn eigen methoden niet noemen? in het volgende voorbeeld kan myObj alleen MyInterface-methoden aanroepen?

MyInterface myObj = new Obj();

Als dit correct is, wat is dan het verschil tussen deze 2 objecten:

MyInterface myObj = new Obj();

MyInterface mySec = new Sec();

Bedankt voor je hulp

12
this kan van pas komen.
toegevoegd de auteur Nerdtron, de bron

8 antwoord

MyInterface myObj = new Obj(); 
MyInterface mySec = new Sec(); 

Om legaal te zijn, moeten zowel Obj en Sec implementeerders van MyInterface zijn. Het verschil tussen deze twee objecten is hoe ze die implementatie bieden. Obj en Sec kunnen twee zeer verschillende of sterk gelijkende dingen doen, maar hun overeenkomst is dat ze zich zouden houden aan een contract waarop u kunt vertrouwen. Beschouw je als een methode

public void doSomethingWith(MyInterface thing) {
     thing.frob();
}

Elk object, myObj en mySec kunnen aan deze methode worden doorgegeven, en deze methode kan dan de frob -methode van dat object gebruiken (ervan uitgaande dat frob deel uitmaakt van de interface-verklaring). Dit is bevrijdend . Hiermee kunt u zeer krachtige dingen doen, door te programmeren op interfaces en niet op implementaties. U kunt bijvoorbeeld de functionaliteit van klassen uitbreiden en een regel code in die klassen niet wijzigen, u geeft eenvoudigweg een andere implementatie van een afhankelijkheid door. U bent niet gebonden aan, of gekoppeld aan , elke implentatie in de methode doSomethingWith .

maar ik lees ook dat als we het object myObj als MyInterface verklaren,   myObj zal zijn eigen methoden (van de klasse Obj) niet kunnen gebruiken, is   dat klopt

Intern blijven instanties van Obj volledige toegang behouden tot de Obj API. myObj is nog steeds een Obj , het zal altijd zijn eigen implementatiedetails kunnen gebruiken.

public interface MyInterface {
    void frob();
}

public class Obj implements MyInterface {

    public void frob() {
        doFrobbing();
    }

    private void doFrobbing() {
        System.out.println("frobbing");
    }

    public static void main(String[] args) {
        MyInterface myObj = new Obj();
        myObj.frob();//still internally calls doFrobbing()
        ((Obj)myObj).doFrobbing();//visible only via class reference
    }
}

Instances van Obj zijn nog steeds instanties van Obj en die instanties kunnen nog steeds doFrobbing gebruiken. Extern kunnen personen die die instanties gebruiken via de interface-verwijzing alleen toegang krijgen tot de interfacemethoden.

17
toegevoegd
bedankt anthony voor deze geweldige uitleg, ik begrijp dit, en meer nog bedankt, maar ik heb ook gelezen dat als we het object myObj als MyInterface verklaren, myObj niet zal zijn in staat om zijn eigen methoden te gebruiken (van de klasse Obj ), klopt dat?
toegevoegd de auteur Paul, de bron
bedankt voor de update, dus wat is het nut om dit te doen? (verbergen van de Obj 's methoden wanneer MyInterface het type is) Een interface "bestaat" om sommige methoden "toe te voegen" aan een object, toch ?, dus waarom het verbergt de andere methoden? (of misschien zijn er geen redenen voor, dit werkt omdat, als algemene regel in elke programmeertaal, een "type" zo werkt?)
toegevoegd de auteur Paul, de bron
Eerst bedankt voor uw antwoord, laten we zeggen: we zijn een project gestart zonder interfaces, en dan willen we een interface implementeren omdat we meer methoden nodig hebben om aan mijn objecten te worden toegevoegd (in mijn eerste bericht: myObj en mySec ): dus we verliezen de vorige methoden van Obj en Sec omdat we myObj en mySec zullen aanduiden als MyInterface 's objecten ... dus we moeten alle code wijzigen, omdat MyInterface de methoden van mijn objecten niet bevat
toegevoegd de auteur Paul, de bron
mmh oke, ik denk dat ik naar enkele voorbeelden moet kijken, maar ik denk dat ik het heb. Bedankt Anthony, grote discussie, maar heel erg bedankt, ik heb je hulp echt gewaardeerd!
toegevoegd de auteur Paul, de bron
Maar onthoud, alleen omdat Obj MyInterface implementeert, ben je niet beperkt tot het alleen maar verwijzen naar myObj via de interface. Je kunt er eenvoudig een instantie van Obj gebruiken die een MyInterface nodig heeft. Dat ergens dat de interface nodig heeft zou het niet uit moeten maken of het een Obj! Als het doet zorg, dan heeft Obj, niet MyInterface nodig.
toegevoegd de auteur Anthony Pegram, de bron
Die methoden zijn niet verloren, niet in het minst. Nu, terwijl u opereert onder de referentie van de interface, zullen de niet-interfacemethoden niet zichtbaar zijn, maar dat is niet hetzelfde als verliezen van de functionaliteit. Het probleem dat ik denk dat je tegenkomt is dat je de interface probeert te gebruiken wanneer dit niet gerechtvaardigd is (je hebt eigenlijk nodig om de non-interface API op een bepaalde methode rechtstreeks aan te roepen), of misschien je hebt code die te veel afhankelijk is en te veel probeert te doen.
toegevoegd de auteur Anthony Pegram, de bron
Als je er verder naar kijkt, zeg je dat je in doSomethingWith zit en dat je te maken hebt met ding . Wat zou je verwachten te zien in ding ? Je kon duidelijk niet naar de API van Obj zoeken, je hebt geen manier om te weten dat je te maken hebt met Obj. Je kunt Sec niet om dezelfde reden zoeken. De enige API die u kent is de API voor MyInterface . Het is die API waarvan u afhankelijk bent. Andere methoden elders kunnen afhankelijk zijn van andere delen van de API van Obj, interface-gedefinieerd of anderszins. Maar hier geven we alleen om de API zoals gedefinieerd door MyInterface.
toegevoegd de auteur Anthony Pegram, de bron
Het gaat terug naar programmeren tegen de interface. Onthoud dat wanneer je een methode zoals doSomethingWith (MyInterface ding) schrijft, je eenvoudigweg niets doet wat else Obj kan doen! U bent alleen geïnteresseerd in het feit dat het frob() kan zijn. Obj geeft zelf om zijn eigen implementatie. Code die direct afhankelijk is van Obj geeft duidelijk om wat Obj kan doen. Maar code die afhankelijk is van de interface hoeft zich alleen zorgen te maken over de interface. Niet echt zeker hoe je het moet uitdrukken om het te laten klikken, maar hopelijk wel.
toegevoegd de auteur Anthony Pegram, de bron
@Paul, goede vraag, antwoord geüpdatet.
toegevoegd de auteur Anthony Pegram, de bron

Er is geen verschil. U kunt alleen interfacemethoden MyInterface aanroepen op myObj en mySec . Het is duidelijk dat uw code alleen zal compileren als zowel de Obj als de Sec de interface implementeren.

1
toegevoegd
Bedankt Strelok, mijn misverstand gaat over het veranderen van het "Type" van een object, en zet de interface als het "Type", dit zou betekenen dat de methoden van obj niet meer "zichtbaar" zijn ... wat me een beetje verwart. Ik heb echter het principe van interfaces, ik begrijp dat interfaces een aantal methoden zijn die door 2 klassen worden gedeeld, maar wat ik niet zeker weet, is: als 'Interface' het type is, hebben de andere methoden uit de myObj-klasse gewonnen ben niet meer zichtbaar
toegevoegd de auteur Paul, de bron
bedankt voor je snelle antwoord, dus hier is het ding: wat als we het project zonder interfaces zijn gestart, en dan willen we een interface implementeren omdat we meer methoden nodig hebben om te worden toegevoegd aan klassen A en B : we verliezen de vorige methoden van A en B omdat we a en b als I's objecten ...
toegevoegd de auteur Paul, de bron
@Paul-interfaces bestaan ​​met het doel om een ​​gemeenschappelijke interface (of met andere woorden een contract) aan verschillende klassen toe te voegen en die klassen daadwerkelijk de functionaliteit volgens het contract te laten uitvoeren. U hoeft geen interfaces te gebruiken als u nieuwe methoden aan een klasse wilt toevoegen. Hier is een duidelijke definitie van wat een interface is: docs.oracle.com /javase/tutorial/java/concepts/interface.html
toegevoegd de auteur Strelok, de bron

Alleen de methoden in de interface zijn zichtbaar , maar alle methoden in het object kunnen nog steeds worden aangeroepen, op voorwaarde dat ze anders toegankelijk worden gemaakt. Bijvoorbeeld:

public interface MyInterface {
    String getName();
}

public class Obj implements MyInterface {
    private String getFirstName() {
        return "John";
    }

    private String getLastName() {
        return "Doe";
    }

    @Override
    public String getName() {
        return getFirstName() + " " + getLastName();
    }
}

public class Sec implements MyInterface {
    private String getDate() {
        return new Date().toString();
    }

    @Override
    public String getName() {
        return getDate();
    }
}

In de bovenstaande gevallen kunnen zowel Obj als Sec hun privéleden bellen, ook al zijn ze niet zichtbaar in andere klassen. Dus als je zegt ...

MyInterface myObj = new Obj();
MyInterface mySec = new Sec();

... zoals je hebt gevraagd in de vraag, terwijl het waar is dat in myObj en mySec de enige zichtbare methode is getName() , de onderliggende implementatie kan anders zijn.

1
toegevoegd
bedankt jonathan voor deze geweldige uitleg, mmh, ok ik begrijp het een beetje meer, dus als Obj 's methoden niet zichtbaar zijn voor andere klassen, in welk geval maakt het uit? (heb je een eenvoudig voorbeeld?)
toegevoegd de auteur Paul, de bron
Sorry, ik weet niet zeker of ik je vraag begrijp.
toegevoegd de auteur Jon Newmuis, de bron
MyInterface myObj = new Obj();
MyInterface mySec = new Sec();

U declareert een exemplaar van een MyInterface met de naam myObj. U initialiseert het met nieuwe Obj (); die is goedgekeurd door de compiler als Obj MyInterface implementeert. myObj kan MyInterface-methoden natuurlijk alleen maar aanroepen. Hetzelfde voor de tweede regel.

Hier is een voorbeeldcode om te proberen:

public class Test {

    public static void main(String args[]){
          A a = new A();
          a.say();
          a.a();

          B b = new B();
          b.say();
          b.b();

          I ia = new A();
          ia.say();
          ia.a();//fail
    }

}

interface i {
    public void say();
}

class A implements i {
    public void say(){
        System.out.println("class A");
    }
    public void a(){
        System.out.println("method a");
    }
}

class B implements i {
    public void say(){
        System.out.println("class B");
    }
    public void b(){
        System.out.println("method b");
    }
}
1
toegevoegd
bedankt kbdjockey voor je antwoord: oke, maar wat als we het project zonder interfaces zijn gestart, en dan willen we een interface implementeren omdat we meer methoden nodig hebben om in klassen te worden toegevoegd A en B : we verliezen de vorige methoden van A en B omdat we a en b zullen declareren als Ik ben objecten ...
toegevoegd de auteur Paul, de bron
Alleen omdat A en B implementeer I betekent niet dat u ze als zodanig moet instantiëren. Je kunt nog steeds A myObj = new A() zeggen en toegang krijgen tot alle methoden van A (inclusief die overschreven door I ).
toegevoegd de auteur Jon Newmuis, de bron
MyInterface mi = new Obj();
mi.getInterfaceMethods(); (methods in the MyInterface)

if(mi instanceof Obj) {
     mi.getObjMethods(); (methods in the Obj)
}
0
toegevoegd

In de code die je liet zien, voer je nooit afgietsels uit.

Een typisch gebruik van een interface is om enkele methoden te definiëren die beschikbaar zullen zijn, zonder rekening te houden met de concrete implementatie.

Een mooi voorbeeld hiervan zijn de luisteraars in de standaard JDK. Bijvoorbeeld de PropertyChangeListener . Dit is een interface die een methode definieert die kan worden aangeroepen wanneer 'een eigenschap wordt gewijzigd'. Een typisch gebruik van deze interface is om deze te koppelen aan een klasse die eigenschappen heeft, en deze klasse zal die listeners waarschuwen wanneer een van de eigenschappen is gewijzigd.

Het maakt de klas niet uit wat die luisteraars zullen doen. Het vertrouwt alleen op het feit dat deze propertyChange -methode aanwezig is en roept die methode aan.

De klasse kan deze methode alleen op de listener aanroepen, omdat deze alleen weet over de methode die in de interface is gedefinieerd. Als die luisteraars andere methoden hebben, kunnen ze die methoden zelf bellen, maar dat is alleen omdat ze weten dat ze meer zijn dan de interface.

0
toegevoegd

Het veranderen van het type van een variabele (dat wil zeggen een referentie) verandert het object zelf niet. Een object kan altijd zijn eigen methoden noemen, ongeacht de typen gedeclareerde variabelen die verwijzing ernaar zijn.

0
toegevoegd

Een simpele analogie:

Overweeg een chef-kok (interface). En er zijn Chinese chef-kok (klassen) en Amerikaanse chef-kok (klassen). Nu is er een hotel dat uitkijkt om een ​​chef-kok te werven op basis van enkele geschiktheidscriteria zoals

  • kan niet-vegeteriaans koken
  • kan vegeteriaans koken
  • heb ervaring van 5 jaar

Hier is de geschiktheid de context waarbinnen de Chef-type persoon wordt geëvalueerd (Typen functionaliteit). Nu kunnen er gevallen zijn waarbij de Chinese chef-kok ook kan koken op zee, Italiaanse gerechten enz., Wat het geval zou kunnen zijn met een Amerikaanse tegenhanger. Al deze kunnen niet relevant lijken voor Hotel manager, omdat hij zich alleen bezig houdt met de vereiste criteria.

Chef-koks werken in een hotel is analoog aan Chef-type-object gebruikt in code. Het voor de hand liggende werk zou zijn om vegeteriaans en niet-vegeteriaans voedsel te bereiden (criteria of interfacemethoden). Dat betekent niet dat het hotel de vaardigheden van de Chinese chef-kok op het gebied van het maken van zeevoedsel niet kan gebruiken.

Het is gewoon een kwestie van specificeren welke vaardigheden (functionaliteit) het hotel zoekt.

Ik hoop dat je het idee begrijpt.

0
toegevoegd