Я выучил что такое классы, но не осилил интерфейсы. Расскажите пожалуйста понятно, что это такое.
Я одно время думал, что интерфейс – это такой абстрактный класс, который поддерживает множественное наследование, поэтому его можно добавить к реальному (не абстрактному) классу при наследовании, соответственно расширив набор функций этого класса. А переменные в интерфейсе есть?
Вот пример использования интерфейсов для реализации умных указателей, который мне подсказали. Исходный код:
var
s: TStrings;
begin
s := TStringList.Create;
try
DoSomething(s);
finally
s.Free;
end;
end;
С помощью интерфейсов этот код можно заменить на такой:
var
s: IShared<TStrings>;
begin
s := Shared<TStringList>.New;
DoSomething(s);
end;
var
s: Shared<TStrings>;
begin
s := TStringList.Create;
DoSomething(s);
end;
Я не понимаю суть этого кода. Например где хранится счётчик, сколько элементов s было создано? И в каких участках кода проверяется, не пора ли удалить неиспользуемые элементы?
"Ты должен сделать добро из зла, потому что его больше не из чего сделать". АБ Стругацкие.
K>>Я выучил что такое классы, но не осилил интерфейсы. Расскажите пожалуйста понятно, что это такое. vsb>Это класс, у которого все методы абстрактные.
Сомневаюсь. В С++ в этом случае можно создать переменную — указатель на объекты такого класса.
В Яве и Сишарпе с интерфейсами что можно делать, кроме реализации и наследования?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, Khimik, Вы писали:
K>Я выучил что такое классы, но не осилил интерфейсы. Расскажите пожалуйста понятно, что это такое. K>Я одно время думал, что интерфейс – это такой абстрактный класс, который поддерживает множественное наследование, поэтому его можно добавить к реальному (не абстрактному) классу при наследовании, соответственно расширив набор функций этого класса. А переменные в интерфейсе есть?
Всё верно. Переменный по идеологии не положено. Properties в интерфейсах можно, это же по сути set/get
K>Вот пример использования интерфейсов для реализации умных указателей, который мне подсказали. Исходный код: K>[...skipped...]
А вот в примерах не интерфейсы, а дженерики (аналог шаблонов в C++).
K>Я не понимаю суть этого кода. Например где хранится счётчик, сколько элементов s было создано? И в каких участках кода проверяется, не пора ли удалить неиспользуемые элементы?
Счётчик и проверка хранится внутри реализации класса Shared<>
Здравствуйте, LaptevVV, Вы писали:
K>>>Я выучил что такое классы, но не осилил интерфейсы. Расскажите пожалуйста понятно, что это такое. vsb>>Это класс, у которого все методы абстрактные. LVV>Сомневаюсь. В С++ в этом случае можно создать переменную — указатель на объекты такого класса. LVV>В Яве и Сишарпе с интерфейсами что можно делать, кроме реализации и наследования?
Точно так же создать переменную-указатель (собственно в жаве все переменные или указатели или примитивные числовые типы).
K>>>>Я выучил что такое классы, но не осилил интерфейсы. Расскажите пожалуйста понятно, что это такое. vsb>>>Это класс, у которого все методы абстрактные. LVV>>Сомневаюсь. В С++ в этом случае можно создать переменную — указатель на объекты такого класса. LVV>>В Яве и Сишарпе с интерфейсами что можно делать, кроме реализации и наследования? vsb>Точно так же создать переменную-указатель (собственно в жаве все переменные или указатели или примитивные числовые типы). vsb>
Ага. Опять что-то типа принципа подстановки...
Класс, который реализует, является типа наследником от интерфейса.
Поэтому можно создавать ссылку на базовый тип, присваивая ей ссыль на производный.
В таком разрезе — да, интерфейс — это абстрактный класс.
В котором запрещены поля-переменные.
Поля константы вроде разрешалось, не?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>Ага. Опять что-то типа принципа подстановки...
Да, для нее они и нужны. Интерфейс это просто описание ЧТО умеет делать данный класс, но без какой-либо реализации.
LVV>Класс, который реализует, является типа наследником от интерфейса.
Имхо, лучше смотреть на это с другой стороны — что "наследование — это есть суть реализация интерфейса базового класса, плюс переиспользование кода базового класса".
Интерфейсы дают полиморфизм, но не отягощены разделением кода с базовым классом. Переиспользование кода базового класса часто хорошо, а часто только лишний груз и связность.
Здравствуйте, Khimik, Вы писали:
K>Я выучил что такое классы, но не осилил интерфейсы. Расскажите пожалуйста понятно, что это такое. K>Я одно время думал, что интерфейс – это такой абстрактный класс, который поддерживает множественное наследование, поэтому его можно добавить к реальному (не абстрактному) классу при наследовании, соответственно расширив набор функций этого класса. А переменные в интерфейсе есть?
K>Вот пример использования интерфейсов для реализации умных указателей, который мне подсказали. Исходный код:
K>
K>Я не понимаю суть этого кода. Например где хранится счётчик, сколько элементов s было создано? И в каких участках кода проверяется, не пора ли удалить неиспользуемые элементы?
Интерфейс — это контракт в чистом его виде, так как интерфейс не содержит его реализацию. Один класс может реализовывать много таких контрактов, поэтому ограничения на множественное наследование интерфейсов нету. Гугли на тему "контрактное программирование".
K>>Я не понимаю суть этого кода. Например где хранится счётчик, сколько элементов s было создано? И в каких участках кода проверяется, не пора ли удалить неиспользуемые элементы?
M>Счётчик и проверка хранится внутри реализации класса Shared<>
Вы явно что-то путаете с моими примерами. Когда в последнем коде вызывается s := TStringList.Create; , вообще причём здесь Shared? Обычное присвоение переменной созданного экземпляра класса TStringList.
"Ты должен сделать добро из зла, потому что его больше не из чего сделать". АБ Стругацкие.
Здравствуйте, fmiracle, Вы писали:
F>Имхо, лучше смотреть на это с другой стороны — что "наследование — это есть суть реализация интерфейса базового класса, плюс переиспользование кода базового класса".
Есть и третья сторона — в разговоре об интерфейсах слово "наследование" должно быть под запретом.
Здравствуйте, vsb, Вы писали:
K>>Я выучил что такое классы, но не осилил интерфейсы. Расскажите пожалуйста понятно, что это такое. vsb>Это класс, у которого все методы абстрактные.
Это не всегда верно, бывают и не абстрактные методы в интерфейсах. Надо про какой-то конкретный язык говорить а то у каждого свое.
K>>>Я не понимаю суть этого кода. Например где хранится счётчик, сколько элементов s было создано? И в каких участках кода проверяется, не пора ли удалить неиспользуемые элементы?
M>>Счётчик и проверка хранится внутри реализации класса Shared<>
K>Вы явно что-то путаете с моими примерами. Когда в последнем коде вызывается s := TStringList.Create; , вообще причём здесь Shared? Обычное присвоение переменной созданного экземпляра класса TStringList.
А переменная типа Shared<> при этом. В Delphi все объекты это указатели. Свежесозданный указатель помещается в класс-контейнер умного указателя, там запоминается и счётчику присваивается единица. Если в s уже что-то хранилось, то сначала счётчик уменьшится, если станет равным нулю, то память, занимаемая предыдущим объектом удалится. Следующая операция, как описано выше: копирование нового указателя, счётчику присваивается 1.
Здравствуйте, LaptevVV, Вы писали:
LVV>Поля константы вроде разрешалось, не?
Нет. Ну если не считать таковыми статические константы, но я на это смотрю, как на пространство имён. Грубо говоря MyInterface.SOME_CONSTANT можно заменить по всей программе на MyInterface_SOME_CONSTANT и ничего не изменится.
Тут надо отметить, что в современной Java в интерфейсы накрутили много дополнительного, например можно делать реализации методов по умолчанию, но это уже отступление от идеи чистых интерфейсов на мой взгляд и сделано скорее для удобства, чем для изменения концепции.
Здравствуйте, Maniacal, Вы писали:
M>Здравствуйте, Khimik, Вы писали:
K>>>>Я не понимаю суть этого кода. Например где хранится счётчик, сколько элементов s было создано? И в каких участках кода проверяется, не пора ли удалить неиспользуемые элементы?
M>>>Счётчик и проверка хранится внутри реализации класса Shared<>
K>>Вы явно что-то путаете с моими примерами. Когда в последнем коде вызывается s := TStringList.Create; , вообще причём здесь Shared? Обычное присвоение переменной созданного экземпляра класса TStringList.
M>А переменная типа Shared<> при этом. В Delphi все объекты это указатели. Свежесозданный указатель помещается в класс-контейнер умного указателя, там запоминается и счётчику присваивается единица. Если в s уже что-то хранилось, то сначала счётчик уменьшится, если станет равным нулю, то память, занимаемая предыдущим объектом удалится. Следующая операция, как описано выше: копирование нового указателя, счётчику присваивается 1.
Мне по-прежнему непонятно.
Пока вот вопрос: умные указатели могут быть реализованы через обычные классы, без интерфейсов?
В последнем примере с Shared<> я совершенно не вижу, где здесь второй объект — счетчик. Я вижу только переменную S, которой присваивается ссылка на создаваемый класс TStringList.
Вот мой пример, как я бы сделал умный счётчик (с моим текущим пониманием всего этого):
var
ProjectPointersCounter:tProjectPointersCounter;
...
var
S:tstringlist;
begin
s:=projectpointerscounter.AddClass(TStringList.Create);
DoSomething(s);
...
projectpointerscounter.CheckEmptyObjects;
И мне всё ещё неясна общая логика, как использовать такую конструкцию, чтобы в другом месте кода обратиться к этому StringList.
"Ты должен сделать добро из зла, потому что его больше не из чего сделать". АБ Стругацкие.
Здравствуйте, GarryIV, Вы писали:
K>>>Я выучил что такое классы, но не осилил интерфейсы. Расскажите пожалуйста понятно, что это такое. vsb>>Это класс, у которого все методы абстрактные.
GIV>Это не всегда верно, бывают и не абстрактные методы в интерфейсах. Надо про какой-то конкретный язык говорить а то у каждого свое.
Ну тут уже вопрос терминологии. Даже понятие указателя в разных языках отличается. В принципе можно считать интерфейс абстрактным классом без полей. А можно вообще считать, что понятия интерфейса нет, а есть только классы. Хотя в той же Java и C# множественное наследование реализовано только для интерфейсов, поэтому в каком-то смысле они там есть в любом случае.
Здравствуйте, Khimik, Вы писали:
K>Я выучил что такое классы, но не осилил интерфейсы. Расскажите пожалуйста понятно, что это такое. K>Я одно время думал, что интерфейс – это такой абстрактный класс, который поддерживает множественное наследование, поэтому его можно добавить к реальному (не абстрактному) классу при наследовании, соответственно расширив набор функций этого класса.
Упрощённо и схематично это вот так:
Абстрактный класс (как и вообще класс) — это дополнительный компонент (методы, свойства и т.п.), который автоматически приписывается к своему наследнику.
Это наследование реализации. То, что класс абстрактный, сути не меняет, просто добавляет контроль, что его невозможно создать без такого наследника.
(По крайней мере, невозможно без специальных наворотов, но это уже отдельная тема).
Интерфейс же никуда не приписывается, а задаёт "шаблон", которому должен соответствовать наследник.
Это не наследование реализации и вообще не наследование. Это реализация интерфейса.
В конкретном языке реализация для этих двух вещей может даже совпадать, но логически это совершенно разные вещи.
То есть, если вы говорите "у человека должна быть нога, если она у него есть — то это человек" — это интерфейс.
Если "Вот нога, если её к кому-то приклеить, то то, что получится можно назвать человеком" — это класс.
Если "Вот заготовка для ноги, если её допилить и приклеить к кому-то, то то, что получится, можно назвать человеком" — это абстрактный класс.
Здравствуйте, vmpire, Вы писали:
V>Абстрактный класс (как и вообще класс) — это дополнительный компонент (методы, свойства и т.п.), который автоматически приписывается к своему наследнику. V>Это наследование реализации. То, что класс абстрактный, сути не меняет, просто добавляет контроль, что его невозможно создать без такого наследника. V>(По крайней мере, невозможно без специальных наворотов, но это уже отдельная тема).
V>Интерфейс же никуда не приписывается, а задаёт "шаблон", которому должен соответствовать наследник. V>Это не наследование реализации и вообще не наследование. Это реализация интерфейса.
Пока для меня по-прежнему слишком мало конкретики.
1) Могут ли у интерфейса быть переменные (поля)?
2) Может ли интерфейс добавить дополнительную процедуру, например, для конструктора или деструктора класса? Т.е. если класс B наследуется от класса A совместно с интерфейсом I, то можно ли сделать, чтобы при каждом вызове конструктора B, кроме кода собственно конструктора B, inherited конструктора A и inherited предыдущих конструкторов вызывалась ещё какая-то процедура, объявленная в I?
"Ты должен сделать добро из зла, потому что его больше не из чего сделать". АБ Стругацкие.
Здравствуйте, LaptevVV, Вы писали:
K>>>Я выучил что такое классы, но не осилил интерфейсы. Расскажите пожалуйста понятно, что это такое. vsb>>Это класс, у которого все методы абстрактные. LVV>Сомневаюсь. В С++ в этом случае можно создать переменную — указатель на объекты такого класса. LVV>В Яве и Сишарпе с интерфейсами что можно делать, кроме реализации и наследования?
Отстали вы от прогресса.
Вот вам Java 8:
// A simple program to Test Interface default
// methods in java interface TestInterface
{
// abstract method public void square(int a);
// default method default void show()
{
System.out.println("Default Method Executed");
}
}
// A simple Java program to TestClassnstrate static
// methods in java interface TestInterface
{
// abstract method public void square (int a);
// static method static void show()
{
System.out.println("Static Method Executed");
}
}
Здравствуйте, Kswapd, Вы писали:
K>Отвратительно . Так испортить гениальную идею чистого интерфейса.
А чем интерфейс не чистый ?
В любом случае определить метод никто не запрещает.