Vra

Die onderwerp sê die meeste van dit - wat is die rede vir die feit dat statiese metodes nie in 'n koppelvlak kan verklaar word

public interface ITest {
    public static String test();
}

Die kode hierbo gee my die volgende fout (in Eclipse, ten minste):. "Onwettige wysiger vir die metode koppelvlak ITest.test (); slegs openbare & abstrakte toegelaat"

Was dit nuttig?

Oplossing

Daar is 'n paar kwessies op die spel hier. Die eerste is die kwessie van waarby 'n statiese metode sonder definieer dit. Dit is die verskil tussen

public interface Foo {
  public static int bar();
}

en

public interface Foo {
  public static int bar() {
    ...
  }
}

Die eerste is onmoontlik vir die redes wat Espo noem. jy weet nie wat die implementering van die klas is die korrekte definisie

Java kan toelaat dat die laasgenoemde; en in waarheid te sê, begin in Java 8, is dit nie!

Ander wenke

Die rede waarom jy nie kan 'n statiese metode in 'n koppelvlak lê in die manier Java besluit statiese verwysings. Java sal nie die moeite op soek na 'n geval van 'n klas tydens 'n poging om 'n statiese metode uit te voer. Dit is omdat statiese metodes is nie byvoorbeeld afhanklik en dus kan direk uit die klas lêer uitgevoer word. Gegee dat alle metodes in 'n koppelvlak is abstrakte, sou die VM het om te kyk vir 'n spesifieke toepassing van die koppelvlak om die kode te vind agter die statiese metode sodat dit kan word uitgevoer. Dit is teenstrydig met dan hoe statiese metode resolusie werk en sou 'n teenstrydigheid in te voer in die taal.

Ek sal jou vraag met 'n voorbeeld te beantwoord. Gestel ons het 'n wiskunde klas met 'n statiese metode byvoeging. Jy sal hierdie metode noem soos so:

Math.add(2, 3);

As Math was 'n koppelvlak in plaas van 'n klas, dit kon nie enige gedefinieerde funksies het. As sodanig, sê iets soos Math.add (2, 3) maak nie sin nie.

Die rede lê in die ontwerp-beginsel, dat java verskeie erfenis nie toelaat. Die probleem met verskeie erfenis kan geïllustreer deur die volgende voorbeeld:

public class A {
   public method x() {...}
}
public class B {
   public method x() {...}
}
public class C extends A, B { ... }

Nou wat gebeur as jy C.x (noem)? Sal wees A.x () of B.x () uitgevoer word? Elke taal met verskeie erfenis het om hierdie probleem op te los.

Interfaces toelaat in Java 'n soort van beperkte verskeie erfenis. Om die probleem hierbo te vermy, is hulle nie toegelaat om metodes te hê. As ons kyk na die dieselfde probleem met koppelvlakke en statiese metodes:

public interface A {
   public static method x() {...}
}
public interface B {
   public static method x() {...}
}
public class C implements A, B { ... }

Dieselfde probleem hier, wat gebeur as jy C.x ()? Bel

Statiese metodes is nie byvoorbeeld metodes. Daar is geen byvoorbeeld konteks, dus om dit te implementeer van die koppelvlak maak min sin.

Nou Java8 stel ons in staat om selfs Statiese metodes in Interface definieer.

interface X {
    static void foo() {
       System.out.println("foo");
    }
}

class Y implements X {
    //...
}

public class Z {
   public static void main(String[] args) {
      X.foo();
      // Y.foo(); // won't compile because foo() is a Static Method of X and not Y
   }
}

Let wel: Metodes in Interface is steeds openbare abstrakte by verstek as ons nie uitdruklik gebruik die sleutelwoorde verstek / statiese om hulle Standaard metodes en statiese metodes resp maak

.

Daar is 'n baie mooi en bondige antwoord op jou vraag hier . (Dit het my opgeval as so 'n mooi eenvoudige manier verduidelik dit wat ek wil om dit te skakel van hier af.)

Dit blyk dat die statiese metode in die koppelvlak kan ondersteun in Java 8 , goed, my oplossing is hulle net te definieer in die binneste klas.

interface Foo {
    // ...
    class fn {
        public static void func1(...) {
            // ...
        }
    }
}

Dieselfde tegniek kan ook gebruik word in aantekeninge:

public @interface Foo {
    String value();

    class fn {
        public static String getValue(Object obj) {
            Foo foo = obj.getClass().getAnnotation(Foo.class);
            return foo == null ? null : foo.value();
        }
    }
}

Die innerlike klas moet altyd verkry word in die vorm van Interface.fn... in plaas van Class.fn..., dan kan jy ontslae te raak van dubbelsinnige probleem.

'n koppelvlak gebruik word vir polimorfisme, wat van toepassing is op voorwerpe, nie tipes. Daarom (soos reeds opgemerk) dit maak geen sin om 'n statiese koppelvlak lid het.

Java 8 Was die wêreld verander jy kan statiese metodes in koppelvlak, maar dit dwing jou om implementering te voorsien vir daardie.

public interface StaticMethodInterface {
public static int testStaticMethod() {
    return 0;
}

/**
 * Illegal combination of modifiers for the interface method
 * testStaticMethod; only one of abstract, default, or static permitted
 * 
 * @param i
 * @return
 */
// public static abstract int testStaticMethod(float i);

default int testNonStaticMethod() {
    return 1;
}

/**
 * Without implementation.
 * 
 * @param i
 * @return
 */
int testNonStaticMethod(float i);

}

Onwettige kombinasie van wysigers: statiese en abstrakte

As 'n lid van 'n klas as statiese verklaar, kan dit gebruik word om met sy klas naam wat beperk is tot daardie klas, sonder om 'n voorwerp.

As 'n lid van 'n klas as abstrakte verklaar, moet jy die klas as abstrakte verklaar en wat jy nodig het om die implementering van die abstrakte lid te voorsien in sy geërf klas (Sub-Klas).

Jy moet 'n uitvoering aan die abstrakte lid van 'n klas in sub-klas waar jy gaan die gedrag van statiese metode verander verskaf, ook verklaar as abstrakte wat 'n beperk is tot die basis klas, wat nie korrek

Sedert statiese metodes nie kan geërf. So geen nut plaas dit in die koppelvlak. Koppelvlak is basies 'n kontrak wat al sy intekenaars moet volg. Die plasing van 'n statiese metode in koppelvlak sal die intekenaars te dwing om dit te implementeer. wat nou word teenstrydig met die feit dat statiese metodes nie kan geërf het.

  

Met Java 8 , koppelvlakke kan nou statiese metodes.

Byvoorbeeld, Comparator het 'n statiese metode naturalOrder ().

Die vereiste dat koppelvlakke nie implementasies kan hê is ook verslap. Koppelvlakke kan nou verklaar "default" metode implementering, wat is soos normale implementering met een uitsondering:. As jy beide 'n standaard implementering van 'n koppelvlak en 'n normale implementering van 'n superklas erf, sal die implementering van die superklas se altyd prioriteit

Miskien is 'n kode voorbeeld sal help, ek gaan om te gebruik C #, maar jy moet in staat wees om saam te volg.

Kom ons maak asof ons 'n koppelvlak genoem IPayable

public interface IPayable
{
    public Pay(double amount);
}

Nou, ons het twee beton klasse wat hierdie koppelvlak implementeer:

public class BusinessAccount : IPayable
{
    public void Pay(double amount)
    {
        //Logic
    }
}

public class CustomerAccount : IPayable
{
    public void Pay(double amount)
    {
        //Logic
    }
}

Nou, kan voorgee ons het 'n versameling van verskeie rekeninge, om dit te doen, sal ons 'n generiese lys van die tipe gebruik IPayable

List<IPayable> accountsToPay = new List<IPayable>();
accountsToPay.add(new CustomerAccount());
accountsToPay.add(new BusinessAccount());

Nou wil ons $ 50,00 betaal om al die rekeninge:

foreach (IPayable account in accountsToPay)
{
    account.Pay(50.00);
}

So nou sien jy hoe koppelvlakke is ongelooflik nuttig.

Hulle word gebruik op net aangehaal voorwerpe. Nie op statiese klasse.

As jy betaal statiese gemaak het, wanneer herhaling deur die IPayable in accountsToPay sou daar geen manier om uit te vind of dit moet bel betaal op BusinessAcount of CustomerAccount wees.

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top