Реализация по умолчанию метода для интерфейсов С#?
Можно ли определить интерфейс на С#, который имеет реализацию по умолчанию? (так что мы можем определить класс, реализующий этот интерфейс без реализации этого конкретного метода по умолчанию).
Я знаю методы расширения (как описано в этой ссылке). Но это не мой ответ, потому что, имея расширение метода, подобное следующему, компилятор все еще жалуется на реализацию MyMethod в MyClass:
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
}
Я спрашиваю об этом, потому что (по крайней мере, насколько я понимаю) это можно сделать на Java (см. здесь).
PS: с абстрактным базовым классом с некоторым методом также является not мой ответ просто потому, что у нас нет множественного наследования в С#, и он отличается от того, по умолчанию для интерфейсов (если возможно!).
Ответы
Ответ 1
Я разрабатываю игры, поэтому часто хочу иметь общую функцию для всех реализаций интерфейса, но в то же время позволяет каждой реализации делать свою собственную вещь, так же, как и функции виртуального/переопределения подкласса.
Вот как я это делаю:
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 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 Move function
// And then it will proceed to executing Robocop 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) { }
}
Ответ 2
Краткий ответ:
Нет, вы не можете написать реализацию метода в интерфейсах.
Описание:
Интерфейсы подобны контракту, так что типы, которые будут наследовать от него, должны будут определить реализацию, если у вас есть сценарий, вам нужен метод с реализацией по умолчанию, тогда вы можете сделать свой класс abstract и определить реализацию по умолчанию для метода, который вы хотите.
Пример:
public abstract class MyType
{
public string MyMethod()
{
// some implementation
}
public abstract string SomeMethodWhichDerivedTypeWillImplement();
}
и теперь в классе Dervied:
public class DerivedType : MyType
{
// now use the default implemented method here
}
Ответ 3
С# v8 начнет допускать реализацию конкретного метода в интерфейсах. Это позволит вашим конкретным классам реализации не прерываться при изменении интерфейсов, которые будут реализованы в будущем.
В следующей версии языка может быть что-то подобное:
interface IA
{
void NotImplementedMethod();
void M() { WriteLine("IA.M"); } //method definition present in the interface
}
Обратитесь к этой проблеме GitHub № 288. Кроме того, Mads Torgersen подробно рассказывает об этой предстоящей функции в этом канале 9 видео.
Примечание. Текущая версия языка С# в состоянии RTM равна v7 во время написания этого ответа.
Ответ 4
Не напрямую, но вы можете определить метод расширения для интерфейса, а затем реализовать его как-то вроде этого
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();
}
}
Изменить *
Важно, чтобы метод расширения и метод, который вы выполняете, называются по-разному, иначе вы, скорее всего, получите stackoverflow.