Использование переменных интерфейса
Я все еще пытаюсь лучше понять интерфейсы. Я знаю, что они представляют и как реализовать их в классах.
Я не понимаю, когда вы создаете переменную, имеющую один из типов интерфейса:
IMyInterface somevariable;
Зачем вам это делать? Я не понимаю, как IMyInterface можно использовать как класс... например, для вызова методов, поэтому:
somevariable.CallSomeMethod();
Зачем вам использовать переменную IMyInterface для этого?
Ответы
Ответ 1
Вы не создаете экземпляр интерфейса - вы создаете экземпляр того, что реализует интерфейс.
Точка интерфейса заключается в том, что он гарантирует, что то, что когда-либо реализует его, предоставит объявленные в нем методы.
Итак, теперь, используя ваш пример, вы могли бы:
MyNiftyClass : IMyInterface
{
public void CallSomeMethod()
{
//Do something nifty
}
}
MyOddClass : IMyInterface
{
public void CallSomeMethod()
{
//Do something odd
}
}
И теперь у вас есть:
IMyInterface nifty = new MyNiftyClass()
IMyInterface odd = new MyOddClass()
Вызов метода CallSomeMethod теперь будет делать что-то отличное или что-то странное, и это становится особенно полезным, когда вы проходите с использованием IMyInterface в качестве типа.
public void ThisMethodShowsHowItWorks(IMyInterface someObject)
{
someObject.CallSomeMethod();
}
Теперь, в зависимости от того, вызываете ли вы вышеуказанный метод с отличным или нечетным классом, вы получаете другое поведение.
public void AnotherClass()
{
IMyInterface nifty = new MyNiftyClass()
IMyInterface odd = new MyOddClass()
// Pass in the nifty class to do something nifty
this.ThisMethodShowsHowItWorks(nifty);
// Pass in the odd class to do something odd
this.ThisMethodShowsHowItWorks(odd);
}
ИЗМЕНИТЬ
Это относится к тому, что, по вашему мнению, относится к вашему заданному вопросу: почему вы объявляете переменную типа интерфейса?
То есть, зачем использовать:
IMyInterface foo = new MyConcreteClass();
в предпочтении:
MyConcreteClass foo = new MyConcreteClass();
Надеюсь, понятно, почему вы должны использовать интерфейс при объявлении подписи метода, но это оставляет вопрос о локально переменных:
public void AMethod()
{
// Why use this?
IMyInterface foo = new MyConcreteClass();
// Why not use this?
MyConcreteClass bar = new MyConcreteClass();
}
Обычно нет технической причины, почему интерфейс предпочтительнее. Обычно я использую интерфейс, потому что:
- Обычно я устанавливаю зависимости, поэтому необходим полиморфизм
- Использование интерфейса четко заявляет о моем намерении использовать только члены интерфейса
Единственное место, где вам нужен технический интерфейс, - это то, где вы используете полиморфизм, например создание вашей переменной с помощью factory или (как я сказал выше) с использованием инъекции зависимостей.
Заимствуя пример из itowlson, используя конкретную декларацию, вы не могли этого сделать:
public void AMethod(string input)
{
IMyInterface foo;
if (input == "nifty")
{
foo = new MyNiftyClass();
}
else
{
foo = new MyOddClass();
}
foo.CallSomeMethod();
}
Ответ 2
Потому что это:
public void ReadItemsList(List<string> items);
public void ReadItemsArray(string[] items);
может стать следующим:
public void ReadItems(IEnumerable<string> items);
Edit
Подумайте об этом так:
Вы должны быть в состоянии сделать это.
а не:
Ты должен быть этим.
По сути, это контракт между методом и его вызывающими.
Ответ 3
Допустим, у вас есть класс "Лодка", "Автомобиль", "Грузовик", "Самолет".
Все они имеют общий метод TakeMeThere (назначение строки)
У вас будет интерфейс:
public interface ITransportation
{
public void TakeMeThere(string destination);
}
то ваш класс:
public class Boat : ITransportation
{
public void TakeMeThere(string destination) // From ITransportation
{
Console.WriteLine("Going to " + destination);
}
}
То, что вы здесь говорите, это то, что мой класс Лодка будет делать все ITransportation и мне тоже.
И тогда, когда вы хотите сделать программное обеспечение для транспортной компании. У вас может быть метод
Void ProvideServiceForClient(ITransportation transportationMethod, string whereTheyWantToGo)
{
transportationMethod.TakeMeThere(whereTheyWantToGo); // Cause ITransportation has this method
}
Так что неважно, какой тип транспорта они хотят, потому что мы знаем, что он может TakeMeThere
Ответ 4
Использование переменных интерфейса - это ТОЛЬКО способ дать возможность писать методы обработчика, которые могут принимать данные от объектов, которые имеют разные базовые классы.
Это примерно так же ясно, как и любой другой.
Ответ 5
Я был в том же положении, и мне потребовалось несколько дней, чтобы понять, почему мы должны использовать переменную интерфейса.
IDepartments rep = new DepartmentsImpl();
почему не
DepartmentsImpl rep = new DepartmentsImpl();
Представьте, что если класс реализует два интерфейса, которые содержат элемент с той же сигнатурой, то реализация этого элемента в классе приведет к тому, что оба интерфейса будут использовать этот элемент в качестве своей реализации.
class Test
{
static void Main()
{
SampleClass sc = new SampleClass();
IControl ctrl = (IControl)sc;
ISurface srfc = (ISurface)sc;
// The following lines all call the same method.
sc.Paint();
ctrl.Paint();
srfc.Paint();
}
}
interface IControl
{
void Paint();
}
interface ISurface
{
void Paint();
}
class SampleClass : IControl, ISurface
{
// Both ISurface.Paint and IControl.Paint call this method.
public void Paint()
{
Console.WriteLine("Paint method in SampleClass");
}
}
// Output:
// Paint method in SampleClass
// Paint method in SampleClass
// Paint method in SampleClass
Если оба члена интерфейса не выполняют одну и ту же функцию, это может привести к неправильной реализации одного или обоих интерфейсов.
public class SampleClass : IControl, ISurface
{
void IControl.Paint()
{
System.Console.WriteLine("IControl.Paint");
}
void ISurface.Paint()
{
System.Console.WriteLine("ISurface.Paint");
}
}
Член класса IControl.Paint доступен только через интерфейс IControl, а ISurface.Paint доступен только через ISurface. Обе реализации метода являются отдельными, и ни один из них не доступен непосредственно в классе. Например:
IControl c = new SampleClass();
ISurface s = new SampleClass();
s.Paint();
Пожалуйста, поправьте меня, если я ошибаюсь, поскольку я все еще изучаю эту концепцию интерфейса.
Ответ 6
Цель интерфейса - определить контракт между несколькими объектами, не зависящими от конкретной реализации.
Таким образом, вы обычно используете его, когда у вас есть Intrace ISomething
и конкретная реализация
class Something : ISomething
Итак, интерфейс varialbe будет использоваться при создании контракта:
ISomething myObj = new Something();
myObj.SomeFunc();
Вы также должны прочитать интерфейс С#
Update:
Я объясню логику использования интерфейса для переменной, а не самого класса примером (реальной жизни):
У меня есть общий интерфейс репозитория:
Interface IRepository {
void Create();
void Update();
}
И у меня есть две отдельные реализации:
class RepositoryFile : interface IRepository {}
class RepositoryDB : interface IRepository {}
Каждый класс имеет совершенно другую внутреннюю реализацию.
Теперь у меня есть другой объект, Logger, который использует уже созданный репозиторий для записи. Этот объект не волнует, как реализуется Репозиторий, поэтому он просто реализует:
void WriteLog(string Log, IRepository oRep);
Кстати, это также можно реализовать, используя наследование стандартных классов. Но разница между использованием интерфейсов и наследованием классов - это еще одно обсуждение.
Для более подробного обсуждения различий между абстрактными классами и интерфейсами см. здесь.
Ответ 7
Скажем, например, у вас есть два класса: Book
и Newspaper
. Вы можете прочитать каждый из них, но на самом деле было бы неразумно, чтобы эти два наследовали от общего суперкласса. Поэтому они будут реализовывать интерфейс IReadable
:
public interface IReadable
{
public void Read();
}
Теперь скажите, что вы пишете приложение, которое будет читать книги и газеты для пользователя. Пользователь может выбрать книгу или газету из списка, и этот элемент будет прочитан пользователю.
Метод в вашем приложении, который читает пользователю, примет этот параметр Book
или Newspaper
в качестве параметра. Это может выглядеть так в коде:
public static void ReadItem(IReadable item)
{
item.Read();
}
Поскольку параметр является IReadable
, мы знаем, что объект имеет метод Read()
, поэтому мы называем его, чтобы прочитать его пользователю. Не имеет значения, является ли это Book
, Newspaper
или что-либо еще, что реализует IReadable
. Отдельные классы реализуют точно, как каждый элемент будет считываться путем реализации метода Read()
, поскольку он, скорее всего, будет отличаться для разных классов.
Book
Read()
может выглядеть так:
public void Read()
{
this.Open();
this.TurnToPage(1);
while(!this.AtLastPage)
{
ReadText(this.CurrentPage.Text);
this.TurnPage();
}
this.Close();
}
Newspaper
Read()
, вероятно, будет немного другим:
public void Read()
{
while(!this.OnBackPage)
{
foreach(Article article in this.CurrentPage.Articles)
{
ReadText(article.Text);
}
}
}
Дело в том, что объект, содержащийся в переменной типа интерфейса, гарантированно имеет на нем определенный набор методов, даже если возможные классы объекта не связаны каким-либо другим способом. Это позволяет вам писать код, который будет применяться к различным классам, которые имеют общие операции, которые могут выполняться на них.
Ответ 8
Это не относится к С#, поэтому я рекомендую перейти к некоторому флагом othere.
для вашего вопроса,
основная причина, по которой мы выбираем интерфейс, - это обеспечить протокол между двумя компонентами (может быть dll, jar или любой другой компонент).
См. Ниже
public class TestClass
{
static void Main()
{
IMyInterface ob1, obj2;
ob1 = getIMyInterfaceObj();
obj2 = getIMyInterfaceObj();
Console.WriteLine(ob1.CallSomeMethod());
Console.WriteLine(obj2.CallSomeMethod());
Console.ReadLine();
}
private static bool isfirstTime = true;
private static IMyInterface getIMyInterfaceObj()
{
if (isfirstTime)
{
isfirstTime = false;
return new ImplementingClass1();
}
else
{
return new ImplementingClass2();
}
}
}
public class ImplementingClass1 : IMyInterface
{
public ImplementingClass1()
{
}
#region IMyInterface Members
public bool CallSomeMethod()
{
return true;
}
#endregion
}
public class ImplementingClass2 : IMyInterface
{
public ImplementingClass2()
{
}
#region IMyInterface Members
public bool CallSomeMethod()
{
return false;
}
#endregion
}
public interface IMyInterface
{
bool CallSomeMethod();
}
Здесь основной метод не знает о классах, все же он может получить другое поведение с помощью интерфейса.
Ответ 9
Используется интерфейс, поэтому вам не нужно беспокоиться о том, какой класс реализует интерфейс. Примером этого может быть использование метода factory, который возвращает конкретную реализацию, которая может быть различной в зависимости от среды, в которой вы работаете. Он также позволяет дизайнеру API определять API, позволяя третьим сторонам реализовать API по своему усмотрению. Sun делает это с помощью этого криптографического API для Java.
public interface Foo {
}
public class FooFactory {
public static Foo getInstance() {
if(os == 'Windows') return new WinFoo();
else if(os == 'OS X') return new MacFoo();
else return new GenricFoo();
}
}
Ваш код, который использует factory, должен знать только о Foo, а не о конкретных реализациях.
Ответ 10
Нет, это невозможно. Дизайнеры не предоставили никакого способа. Конечно, это тоже здравый смысл. Поскольку интерфейс содержит только абстрактные методы, и поскольку абстрактные методы не имеют тела (кода реализации), мы не можем создать объект.
Предположим, что даже если это разрешено, какое использование. Вызов абстрактного метода с объектом не дает никакой цели, как никакого вывода. Нет функциональности для абстрактных методов.
Затем, что такое использование интерфейсов в Java-дизайне и кодировании. Они могут использоваться в качестве прототипов, из которых вы можете легко создавать новые классы. Они работают как шаблоны для других классов, которые реализуют интерфейс так же, как синий шрифт, чтобы построить здание.
Ответ 11
Я считаю, что все отвечают на полиморфную причину использования интерфейса, и Дэвид Холл частично затрагивает, почему вы ссылаетесь на него как на интерфейс, а не на фактическое имя объекта. Разумеется, ограниченность членов интерфейса и т.д. Полезна, но другой ответ - инъекция/создание зависимостей.
Когда вы разрабатываете приложение, оно обычно чище, проще в управлении и более гибко, если вы это делаете, используя инъекцию зависимостей. Сначала он чувствует себя взад-вперед, если вы никогда этого не делали, но когда вы начинаете отступать, вы пожелаете, чтобы вы это сделали.
Инъекционная инъекция обычно работает, позволяя классу создавать экземпляры и управлять зависимостями, и вы просто полагаетесь на интерфейс требуемого объекта.
Пример:
Сначала слейте приложение. Логика уровня 1, интерфейс уровня 2, инъекция зависимости уровня 3. (У каждого свой путь, это просто для шоу).
В логическом уровне вы ссылаетесь на интерфейсы и уровень зависимости, а затем, наконец, вы создаете логику, основанную только на интерфейсах посторонних объектов.
Здесь мы идем:
public IEmployee GetEmployee(string id)
{
IEmployee emp = di.GetInstance<List<IEmployee>>().Where(e => e.Id == id).FirstOrDefault();
emp?.LastAccessTimeStamp = DateTime.Now;
return emp;
}
Обратите внимание на то, как мы используем di.GetInstance для получения объекта из нашей зависимости. Наш код в этом уровне никогда не узнает или не заботится о объекте Employee. Фактически, если он изменится в другом коде, он никогда не затронет нас здесь. Если изменится интерфейс IEmployee, нам может потребоваться внести изменения в код.
Дело в том, что IEmployee emp = никогда не знает, что такое фактический объект, но знает интерфейс и как с ним работать. Имея это в виду, это когда вы хотите использовать интерфейс, а не объект, потому что мы никогда не знаем или не имеем доступа к объекту.
Это обобщается. Надеюсь, это поможет.
Ответ 12
Это фундаментальное понятие в объектно-ориентированном программировании - полиморфизм. (wikipedia)
Короткий ответ заключается в том, что с помощью интерфейса в классе A вы можете дать классу A любую реализацию IMyInterface
.
Это также форма свободной связи (wikipedia) - где у вас много классов, но они явно не полагаются друг на друга - только на абстрактном понятии набора свойств и методов, которые они предоставляют (интерфейс).