#c# #interface #multiple-inheritance
#c# #интерфейс #множественное наследование
Вопрос:
У меня есть проект с множеством интерфейсов с перекрывающимися методами вычисления:
public interface Interface1
{
public double CalcStuff( int x );
}
public interface Interface2
{
public double CalcStuff( int x );
}
public interface InterfaceJoined : Interface1, Interface2
{
}
public class ClassJoined : InterfaceJoined
{
public double CalcStuff( int x ) { return x*x; }
}
Я хочу, чтобы реализующий класс можно было назначать как все три интерфейса Interface1, Interface2, InterfaceJoined
.
Interface1 calculator1 = new ClassJoined( );
Interface2 calculator2 = new ClassJoined( );
InterfaceJoined calculatorJoined = new ClassJoined( );
double result1 = calculator1.CalcStuff( 20 ); // works
double result2 = calculator2.CalcStuff( 20 ); // works
double resultJoined = calculatorJoined.CalcStuff( 20 ); // "the call is ambiguous between the following methods or properties"
Я хочу, чтобы интерфейсы имели одинаковую реализацию. Здесь не нужно различать. Как я могу этого добиться? Является ли вся эта идея плохим дизайном?
Спасибо и приветствия.
Комментарии:
1. Вы можете явно указать, какая реализация предназначена для какого интерфейса: learn.microsoft.com/en-us/dotnet/csharp/programming-guide /…
2. Я не могу найти ситуацию с общедоступным интерфейсом InterfaceJoined: Interface1, Interface2 в вашей ссылке.
3. То, что вы хотите сделать, как вы выразились, не сработает. Сообщение об ошибке довольно четкое. Если бы вы были компилятором, какой из них вы бы выполнили? Вы можете либо выбрать одну версию случайным образом, либо, как это бывает, выдать исключение, потому что вызов неоднозначен. Вы предполагаете, что он будет иметь точно такую же реализацию, но вы можете делать что-то другое в каждом методе (явная реализация), даже если это не имеет смысла, вас ничто не останавливает, поэтому компилятор не может делать предположения здесь.
4.Возможно, наоборот: вы могли бы извлечь общие методы для разделения базовых интерфейсов и вывести из них свои существующие интерфейсы, т.е.
interface ICalcStuff { double CalcStuff(int x); }
а затемinterface Interface1 : ICalcStuff { }
interface Interface2 : ICalcStuff { }
иclass ClassJoined : Interface1, Interface2 { }
5. Да, это было бы возможно, но в конечном итоге привело бы к большому дереву наследования интерфейса, потому что у меня очень часто возникает такая ситуация.
Ответ №1:
Единственное, что я смог придумать, это объединить явную реализацию метода по умолчанию для интерфейса со скрытием методов Interface1.CalcStuff
и Interface2.CalcStuff
с помощью new
ключевого слова:
public interface InterfaceJoined : Interface1, Interface2
{
double Interface1.CalcStuff(int x) => CalcStuff(x);
double Interface2.CalcStuff(int x) => CalcStuff(x);
new double CalcStuff(int x);
}