Подтвердить что ты не робот

Использование переменных интерфейса

Я все еще пытаюсь лучше понять интерфейсы. Я знаю, что они представляют и как реализовать их в классах.

Я не понимаю, когда вы создаете переменную, имеющую один из типов интерфейса:

IMyInterface somevariable;

Зачем вам это делать? Я не понимаю, как IMyInterface можно использовать как класс... например, для вызова методов, поэтому:

somevariable.CallSomeMethod();

Зачем вам использовать переменную IMyInterface для этого?

4b9b3361

Ответ 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) - где у вас много классов, но они явно не полагаются друг на друга - только на абстрактном понятии набора свойств и методов, которые они предоставляют (интерфейс).