Я объясняю концепцию мирян, используя аналогию, понятную большинству людей, - пластиковое литье.
Интерфейс определяет форму объекта точно так же, как форма будет обеспечивать форму готового изделия..
Вы можете залить форму белым пластиком, синим пластиком, чем-то экзотическим, например, эпоксидной смолой или глиной.
Важно то, что независимо от того, из чего они сделаны, у них всех естьта же самая единообразная форма для покупателя продукта.
Для кода это означает, что независимо от того, какой код используется для реализации интерфейса, все они следуют одному и тому же согласованному контракту / форме для конечного пользователя.
Надеюсь, это немного поможет.
Редактировать -
Чтобы расширить аналогию с абстрактными классами, представьте себе следующий шаг в процессе формования.Вы запускаете производство белого, синего и красного пластика, но затем каждый предмет должен быть окрашен на отдельном заводе, мы просто отправляем его.
Элемент не закончен, но он имеет свою формуопределены.Позже придет кто-то и заполнит детали, которые наша фабрика оставила пустыми.
Эти предметы нельзя продать, пока они не получат последний шаг рисования.
В коде абстрактная реализация интерфейса обеспечиваетнекоторые (или никакие) реализации, но оставляют другой класс-потомок для завершения контракта, и таким же образом никто не может создать экземпляр класса, пока контракт не будет завершен.
Таким же образомтем не менее, вы все равно можете ссылаться на абстрактный класс в коде, точно так же, как вы можете ссылаться на неокрашенный элемент пресс-формы как на «белый отлитый в форму предмет», увядающий или не окрашенный!*
Вот краткий пример
void Main()
{
//IMold mold = new IMold(); // error - can't create instance of an interface
//Fruit fruit = new Fruit(); // error - can't create instance of an abstract class
Apple apple1 = new Apple(); // good
Orange orange1 = new Orange(); // good
Fruit apple2 = (Fruit)apple1; // good - Apples are fruit
Fruit orange2 = (Fruit)orange1; // good - oranges are fruit
IFruitMold apple3 = (IFruitMold)apple2; // good - Apples fit the Mold
IFruitMold orange3 = (IFruitMold)orange2; // good - Oranges also fit the mold
//now I can do this:
//Notice that `fruits` is of type IList<T> but the new is List<T>
//This is the exact concept we are talking about
//IList<T> is some kind of set of items that can be added or subtracted from
//but we don't have to care about the implementation details of *HOW* this is done
IList<IFruitMold> fruits = new List<IFruitMold>();
fruits.add(apple3);
fruits.add(orange3);
foreach( var fruit in fruits )
{
fruit.PlasticColor.Dump(); // ok I can read
fruit.PlasticColor = ""; // error - no Set defined in the interface
// depending on the **implementation details** of what type of fruit this is true or false
// we don't care in the slightest, we just care that we have some IFruitMold instances
fruit.RequiresPainting.Dump();
}
}
interface IFruitMold
{
string PlasticColor { get; }
bool RequiresPainting { get; }
}
abstract class Fruit : IFruitMold
{
private string m_PlasticColor = string.Empty;
public string PlasticColor { get; private set; }
public abstract bool RequiresPainting { get; }
}
//notice that we only define the abstract portion of the base class
//it defined PlasticColor for us already!
//the keyword `override` is required - it is to make it clear that
//this member is overriding a member from it's parent.
class Apple : Fruit
{
public override bool RequiresPainting { get { return true; } }
}
class Orange : Fruit
{
public override bool RequiresPainting { get { return false; } }
}