webentwicklung-frage-antwort-db.com.de

Standardimplementierung einer Methode für C # -Schnittstellen?

Kann in C # eine Schnittstelle mit einer Standardimplementierung definiert werden? (damit wir eine Klasse definieren können, die diese Schnittstelle implementiert, ohne diese bestimmte Standardmethode zu implementieren).

Ich kenne Erweiterungsmethoden (wie in diesem Link zum Beispiel). Aber das ist nicht meine Antwort, da der Compiler mit einer Methodenerweiterung wie der folgenden klagt, dass er MyMethod in MyClass implementiert hat:

public interface IMyInterface
{
    string MyMethod();
}

public static class IMyInterfaceExtens
{
    public static string MyMethod(this IMyInterface someObj)
    {
        return "Default method!";
    }
}

public class MyClass: IMyInterface
{
// I want to have a default implementation of "MyMethod" 
// so that I can skip implementing it here
}

Ich frage das, weil es (zumindest soweit ich es verstehe) in Java möglich ist (siehe hier ).

PS: eine abstract-Basisklasse mit einer Methode zu haben, ist auch not meine Antwort, einfach weil wir in C # keine Mehrfachvererbung haben und es sich von einer Standardimplementierung für Schnittstellen unterscheidet (wenn möglich!) .

22
Akhir

Ich entwickle Spiele, so dass ich häufig eine gemeinsame Funktion für alle Implementierungen einer Schnittstelle haben möchte, gleichzeitig aber zulassen kann, dass jede Implementierung ihr eigenes Ding ausführt, ähnlich wie die Virtual/Override-Methoden einer Unterklasse.

So mache ich es:

public class Example
{
    void Start()
    {
        WallE wallE = new WallE();
        Robocop robocop = new Robocop();

        // Calling Move() (from IRobotHelper)
        // First it will execute the shared functionality, as specified in IRobotHelper
        // Then it will execute any implementation-specific functionality,
        // depending on which class called it. In this case, WallE's OnMove().
        wallE.Move(1);

        // Now if we call the same Move function on a different implementation of IRobot
        // It will again begin by executing the shared functionality, as specified in IRobotHlper's Move function
        // And then it will proceed to executing Robocop's OnMove(), for Robocop-specific functionality.
        robocop.Move(1);

        // The whole concept is similar to inheritence, but for interfaces.
        // This structure offers an - admittedly dirty - way of having some of the benefits of a multiple inheritence scheme in C#, using interfaces.
    }

}

public interface IRobot
{
    // Fields
    float speed { get; }
    float position { get; set; }

    // Implementation specific functions.
    // Similar to an override function.
    void OnMove(float direction);
}

public static class IRobotHelper
{
    // Common code for all IRobot implementations. 
    // Similar to the body of a virtual function, only it always gets called.
    public static void Move(this IRobot iRobot, float direction)
    {
        // All robots move based on their speed.
        iRobot.position += iRobot.speed * direction;

        // Call the ImplementationSpecific function
        iRobot.OnMove(direction);
    }
}

// Pro-Guns robot.
public class Robocop : IRobot
{
    public float position { get; set; }

    public float speed { get; set;}

    private void Shoot(float direction) { }

    // Robocop also shoots when he moves
    public void OnMove(float direction)
    {
        Shoot(direction);
    }
}

// Hippie robot.
public class WallE : IRobot
{
    public float position { get; set; }

    public float speed { get; set; }

    // Wall-E is happy just moving around
    public void OnMove(float direction) { }
}

C # v8 wird nun auch die Implementierung von Methoden in Schnittstellen ermöglichen. Dadurch können Ihre konkreten Implementierungsklassen nicht beschädigt werden, wenn Sie die Schnittstellen ändern, die in der Zukunft implementiert werden.

So etwas wird in der nächsten Sprachversion möglich sein:

interface IA
{
    void NotImplementedMethod();
    void M() { WriteLine("IA.M"); } //method definition present in the interface
}

Bitte lesen Sie diese GitHub Ausgabe # 288 . Auch Mads Torgersen spricht ausführlich über dieses kommende Feature im this channel 9-Video.

Note: Aktuelle Version der C # -Sprache im RTM Status ist v7 zum Zeitpunkt des Schreibens dieser Antwort.

18
RBT

Kurze Antwort:

Nein, Sie können keine Implementierung der Methode in Schnittstellen schreiben.

Beschreibung:

Schnittstellen sind wie Verträge, so dass die Typen, die davon erben werden, die Implementierung definieren müssen. Wenn Sie ein Szenario haben, benötigen Sie eine Methode mit Standardimplementierung. Dann können Sie Ihre Klasse abstract und erstellen Definieren Sie die Standardimplementierung für die gewünschte Methode.

Zum Beispiel:

public abstract class MyType
{
    public string MyMethod()
    {
      // some implementation
    }

    public abstract string SomeMethodWhichDerivedTypeWillImplement();
}

und jetzt in der Dervied-Klasse:

public class DerivedType : MyType
{
  // now use the default implemented method here
}

UPDATE (C # 8 wird dies unterstützen):

C # 8 erlaubt eine Standardimplementierung in Schnittstellen

15
Ehsan Sajjad

Nicht direkt, aber Sie können eine Erweiterungsmethode für eine Schnittstelle definieren und diese dann wie folgt implementieren

public interface ITestUser
{
    int id { get; set; }
    string firstName { get; set; }
    string lastName { get; set; }

    string FormattedName();
}

static class ITestUserHelpers
{
    public static string FormattedNameDefault(this ITestUser user)
    {
        return user.lastName + ", " + user.firstName;
    }
}

public class TestUser : ITestUser
{
    public int id { get; set; }
    public string firstName { get; set; }
    public string lastName { get; set; }

    public string FormattedName()
    {
        return this.FormattedNameDefault();
    }
}

Bearbeiten Sie * Es ist wichtig, dass die Erweiterungsmethode und die Methode, die Sie implementieren, einen anderen Namen haben.

5
Tim M

Als Newbe C # -Programmierer las ich dieses Thema durch und fragte mich, ob das folgende Codebeispiel hilfreich sein könnte (ich weiß nicht einmal, ob dies der richtige Weg ist). Für mich erlaubt es mir, das Standardverhalten hinter einer Schnittstelle zu kodieren. Beachten Sie, dass ich die generische Typangabe verwendet habe, um eine (abstrakte) Klasse zu definieren.

namespace InterfaceExample
{
    public interface IDef
    {
        void FDef();
    }

    public interface IImp
    {
        void FImp();
    }

    public class AbstractImplementation<T> where T : IImp
    {
        // This class implements default behavior for interface IDef
        public void FAbs(IImp implementation)
        {
            implementation.FImp();
        }
    }

    public class MyImplementation : AbstractImplementation<MyImplementation>, IImp, IDef
    {
        public void FDef()
        {
            FAbs(this);
        }
        public void FImp()
        {
            // Called by AbstractImplementation
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyImplementation MyInstance = new MyImplementation();

           MyInstance.FDef();
        }
    }
}
0
Jurgen Wilsch