#c# #interface #casting
#c# #интерфейс #Кастинг
Вопрос:
Я понимаю, как работает написание интерфейса на C #, как, например, описано здесь: объяснение codeguru
interface IIntelligence
{
bool intelligent_behavior();
}
class Human: IIntelligence
{
public Human()
{
//.............
}
/// Interface method definition in the class that implements it
public bool intelligent_behavior()
{
Console.WriteLine("........");
return true
}
}
Однако меня смущает следующий процесс кастинга интерфейса:
Human human = new Human();
// The human object is casted to the interface type
IIntelligence humanIQ = (IIntelligence)human;
humanIQ.intelligent_behavior();
Какой смысл в том, чтобы класс (в данном случае Human) реализовал интерфейс, а затем вернул свой экземпляр human обратно в интерфейс? Вопрос не в том, как это работает, а в том, почему это делается.
Ответ №1:
.net предлагает два типа реализаций интерфейса — неявную реализацию и явную реализацию.
Когда вы используете неявную реализацию, она станет частью самого интерфейса типа, например, если у вас есть интерфейс IPerson, подобный этому :
public interface IPerson
{
string Name{get;}
}
и вы реализуете это следующим образом :
public class Person:IPerson
{
public string Name{get; ....}
}
вы можете получить к нему доступ следующим образом (неявно):
aPerson.Name;
но если вы реализуете это вот так (явно) :
public class Person:IPerson
{
string IPerson.Name{get; ....} // notice that there's no need to include access modifier.
}
Тогда к нему можно получить доступ только с помощью интерфейса IPerson:
((IPerson)aPerson).Name;
Обновить:
На самом деле, явная реализация интерфейса позволяет нам реализовывать разные интерфейсы с элементами, имеющими одинаковое имя.(как показано в этом руководстве)
Ответ №2:
Иногда вы можете не знать, что такое объект, но вы знаете, что он реализует определенный интерфейс.
Комментарии:
1. Может случиться, я думаю, вы бы сделали
baseObject is IInterface
для проверки. Любопытно, что параметр методаIInterface
еще не введен.
Ответ №3:
Краткий и популярный пример. Мы можем реализовать такой код: interface IIntelligence { string Talk(); }
class Cat: ICreature
{
public string Talk()
{
Console.WriteLine("Meow!");
return true
}
}
class Dog: ICreature
{
public string Talk()
{
Console.WriteLine("Arf!");
return true
}
}
class Human: ICreature
{
public string Talk()
{
Console.WriteLine("Hello!");
return true
}
}
И тогда мы можем использовать следующий код:
ICreature() creatures = new ICreature(){new Human(), new Dog(), new Cat()};
foreach(IIntelligence creature in creatures){
Console.WriteLine(creature.Talk());
}
Более подробную информацию смотрите в разделе «Полиморфизм в объектно-ориентированном программировании» в Google.
Ответ №4:
Это для получения доступа к явной реализации интерфейса.
Иногда вы хотите скрыть тот факт, что класс реализует интерфейс. Это делается путем явной реализации интерфейса.
public class MyClass : IInterface
{
string IInterface.TheMethod(){}
}
Ответ №5:
По той же причине, по которой вы приводите производный класс обратно к его базовому классу.
Ответ №6:
Рассмотрим эту ситуацию. Я добавил метод к вашему примеру.
interface IIntelligence
{
bool intelligent_behavior();
}
class Human: IIntelligence
{
public Human() { }
/// Interface method definition in the class that implements it
public bool IIntelligence.intelligent_behavior()
{
Console.WriteLine("........");
return true;
}
//Some other method definition
public bool intelligent_behaviour()
{
return false;
}
}
Вы бы выполнили приведение в IIntelligence
, чтобы получить желаемую реализацию метода.
Ответ №7:
Я обнаружил, что приведение к интерфейсу полезно при разработке плагинов для основного приложения. Я создал три проекта. Первый проект ‘connectorInterface’ содержит только одно определение класса, которое является inteface. Код интерфейса:
public interface IConnectorDataReader
{
int ColumnCount
{
get;
}
bool readNextRecord();
string this[int i]
{
get;
}
void reset();
}
Второй проект ‘DataSource1’ (плагин для основного приложения) реализует интерфейс IConnectorDataReader, а также класс, который реализует интерфейс, имеет некоторые дополнительные частные методы. Третий проект ‘main application’ при использовании плагина ‘DataSource1’ использует этот код для чтения данных из плагина ‘DataSource1’:
Assembly assembly = Assembly.LoadFile(path); // path to dll
Type type = assembly.GetType("dataSource1.DataReader");
object myInstance = Activator.CreateInstance(type);
MethodInfo method = type.GetMethod("getConnectorDataReader");
object data = method.Invoke(myInstance, null);
IConnectorDataReader reader =(IConnectorDataReader)data;
// method usage
while (reader.readNextRecord() == true) ....
В моем случае кастинг полезен для чтения данных плагинов. Мне все равно, как реализован плагин, главное, чтобы он реализовывал common interface. Все, что меня волнует и что я использую, — это обычные методы для чтения данных. Я полагаю, что интерфейсы полезны, а также возвращают к интерфейсам.