Здравствуйте, hattab, Вы писали:
H>Здравствуйте, gandjustas, Вы писали:
H>>>Терминология твоя просто жуть. Классы не наследуются от интерфейсов, они их реализуют. Наличие в классе методов _AddRef, _Release, QueryInterface не делает его автоматически реализующим IUnknown.
G>>С чего ты взял?
G>>COM можно писать на C (обычном, без плюсов). Там вообще нет понятия интерфейса. Так ДОСТАТОЧНО реализовать _AddRef, _Release, QueryInterface
H>Мы тут о Delphi говорим, если ты не понял
COM — банарный формат. Ком объекты в делфи не отличаются от COM объектов на C, на C++ и даже на ассемблере.
Если есть отличия, то это на совести компиляторов.
Здравствуйте, gandjustas, Вы писали:
H>>Мамут, ты запарил, ей богу... Передай, пожалуйста, по DCOM, динамический массив из анси-строк. Если при этом у тебя проблем с маршалингом не возникнет, я съем свои носки, а ты сможешь сказать, что в Delphi все интерфейсы COM-совместимы. Еще раз тебе повторяю, INonCOMObject не будет являться COM-совместимым вне зависимости от того, реализует класс методы IUnknown или нет. G>Ты свсем тупой чтоли? Даже не понимаешь разнице между COM и DCOM? Кстати я тебе пост на эту тему кидал.
DCOM -- distributed COM. Ну, сделай тоже самое средствами COM. Я посмотрю, как ты обделаешься.
H>>Я тебе уже наглядно продемонстрировал, что можно сделать класс недекларирующий реализацию IUnknown, но реализующий INonCOMObject (наследованый от IUnknown), и от объектов этого класса невозможно будет получить IUnknown. Думай. G>Еще одна бага в делфи? G>В других языках (в C++ к примеру) при таком раскладе можно получить IUnknown.
Я говорю вот о чем: получив от объекта IMyInterface, ты можешь присвоить его переменной типа IUnknown (собственно, это даже обсуждать глупо). Но! Сделав MyIntf.QueryInterface(IUnknown, UnknownIntf) ты обломаешься. Обломаешься ты у в случае попытки прямого получения IUnknown от объекта (UnknownIntf := TMyObject.Create).
Здравствуйте, hattab, Вы писали:
H>DCOM -- distributed COM. Ну, сделай тоже самое средствами COM. Я посмотрю, как ты обделаешься.
Ликбез. COM — бинарный формат повтороно используемых компонент. DCOM — стандарт для вызова COM объектов между процессами.
Если у тебя INPROC сервер, то на него ограничения DCOM не действют.
H>Я говорю вот о чем: получив от объекта IMyInterface, ты можешь присвоить его переменной типа IUnknown (собственно, это даже обсуждать глупо). Но! Сделав MyIntf.QueryInterface(IUnknown, UnknownIntf) ты обломаешься. Обломаешься ты у в случае попытки прямого получения IUnknown от объекта (UnknownIntf := TMyObject.Create).
Значит бага делфи, в на других языках тоже самое отлично работает.
Более того, если бы такое не работало в принцибе, не работал бы COM вообще.
Вот что Бокс пишет по этому поводу:
Свойство рефлективности QueryInterface гарантирует, что любой интерфейсный указатель сможет удовлетворить запросы на IUnknown, поскольку все интерфейсные указатели неявно принадлежат к типу IUnknown. Спецификация СОМ имеет немного больше ограничений при описании результатов запросов QueryInterface именно на IUnknown. Объект не только должен отвечать «да» на запрос, он должен также возвращать в ответ на каждый запрос в точности одно и то же значение указателя.
Здравствуйте, gandjustas, Вы писали:
H>>>>Терминология твоя просто жуть. Классы не наследуются от интерфейсов, они их реализуют. Наличие в классе методов _AddRef, _Release, QueryInterface не делает его автоматически реализующим IUnknown.
G>>>С чего ты взял?
G>>>COM можно писать на C (обычном, без плюсов). Там вообще нет понятия интерфейса. Так ДОСТАТОЧНО реализовать _AddRef, _Release, QueryInterface
H>>Мы тут о Delphi говорим, если ты не понял G>COM — банарный формат. Ком объекты в делфи не отличаются от COM объектов на C, на C++ и даже на ассемблере. G>Если есть отличия, то это на совести компиляторов.
Речь не о бинарной совместимости. Речь об особенностях реализации.
Здравствуйте, gandjustas, Вы писали:
H>>DCOM -- distributed COM. Ну, сделай тоже самое средствами COM. Я посмотрю, как ты обделаешься. G>Ликбез. COM — бинарный формат повтороно используемых компонент. DCOM — стандарт для вызова COM объектов между процессами. G>Если у тебя INPROC сервер, то на него ограничения DCOM не действют.
А у нас, что, примерение COM ограничено inproc-серверами? Давай пример с предачей динамического массива из анси-строк.
H>>Я говорю вот о чем: получив от объекта IMyInterface, ты можешь присвоить его переменной типа IUnknown (собственно, это даже обсуждать глупо). Но! Сделав MyIntf.QueryInterface(IUnknown, UnknownIntf) ты обломаешься. Обломаешься ты у в случае попытки прямого получения IUnknown от объекта (UnknownIntf := TMyObject.Create).
G>Значит бага делфи, в на других языках тоже самое отлично работает. G>Более того, если бы такое не работало в принцибе, не работал бы COM вообще.
Это не бага. Просто ты тут пытаешься натянуть свое видение на окружающий мир, а он многообразен.
G>Вот что Бокс пишет по этому поводу: G>
G> Свойство рефлективности QueryInterface гарантирует, что любой интерфейсный указатель сможет удовлетворить запросы на IUnknown, поскольку все интерфейсные указатели неявно принадлежат к типу IUnknown. Спецификация СОМ имеет немного больше ограничений при описании результатов запросов QueryInterface именно на IUnknown. Объект не только должен отвечать «да» на запрос, он должен также возвращать в ответ на каждый запрос в точности одно и то же значение указателя.
Я еще могу сказать, что в Delphi есть интерфейсы не имеющие GUID (правда под нативом они не сильно юзабельны)
G>>Значит бага делфи, в на других языках тоже самое отлично работает. G>>Более того, если бы такое не работало в принцибе, не работал бы COM вообще.
H>Это не бага. Просто ты тут пытаешься натянуть свое видение на окружающий мир, а он многообразен.
Угу, это не бага. Это очередной ляп в реализации Делфи (если это вообще так и ты не вешаешь нам лапшу на уши).
Вот этот код прекрасно выполняется на C#. При чем кастинг выполняется неявно:
interface IMyIntA
{
void GetA();
}
interface IMyIntB : IMyIntA
{
void GetB();
}
public class MyObjB : IMyIntB
{
public void GetB()
{
System.Console.WriteLine("IMyIntB.GetB");
}
public void GetA()
{
System.Console.WriteLine("IMyIntA.GetA");
}
}
class Program
{
static void Main(string[] args)
{
MyObjB obj = new MyObjB();
IMyIntA a = obj;
a.GetA();
}
}
M>>// IUnknown декларирует _AddRef, _Release, QueryInterface
M>>IntermediateInterface : Interface(IUnknown)
M>>begin
M>>// в дополнение к трем предыдущим методам мы добавляем
M>>function GetData() : AnsiString
M>>end
M>>FinalInterface : Interface(IntermediateInterface)
M>>begin
M>>// в дополнение к четырем предыдущим
M>>procedure DoSmth();
M>>end
M>>MyClass: Class(FinalInterface)
M>>begin
M>> // какие методы должен реализовать MyClass?
M>>end
M>>
H>Смотря от чего наследуется. Если наследуется от класса реализующего IUnknown, то только методы GetData и DoSmth; Если от обычного класса, то реализовать необходимо все 5 методов.
H>Вот еще посмотри:
H>
H>// Объект реализующий только IMyInterface
H>TMyObject = Class(TObject, IMyInterface)
H>...
H>End;
H>// Объект реализующий, и IUnknown, и IMyInterface
H>TMyObject2 = Class(TObject, IUnknown, IMyInterface)
H>...
H>End;
H>
H>В этом примере, от объекта класса TMyObject ты не сможешь получить IUnknown несмотря на то, что IMyInterface наследован от него.
Все. Дельфи идет в лес семимильными шагами. Настолько испоганить идею наследования — это надо постараться.
"Вот у вас наследование, но это не наследование". "Вот у вас цепочка предков, но вы можете забить на то, что обозначено в любом из их предков, кроме ближайшего". "Если я родитель класса, то класс обязан реализовывать мои методы, а если дед — то необязан"
О. Кстати. Последняя фраза очень четко показывает кривизну такой реализации. Почему класс обязан реализовывать только методы непосредственного предка, а не всех предков по цепочке? Куда подевались методы всех предков? Если мы расширяем базовый интерфейс, разве это не значит, что методы предков никуда не подевались?
То есть, какой смысл писать:
MyInterface : Interface(IUnknown)
если класс, реализующий MyInterface может спокойно похерить реализацию методов из IUnknown?
Здравствуйте, hattab, Вы писали:
H>>>Рекомендуемый/пропогандируемый/самый популярный/(подставь сам) подход может быть не идеальным. Если следуя ему легко сотворить корягу -- она таки будет сотворена (вспомним нападки на Delphi за то, что малограмотные кодеры размещали всю логику в обработчиках формы. Казалось бы, причем тут Delphi?). Еще пояснения нужны?
___>>Не помню таких нападок. Т.е. ты считаешь, что использование конфигов есть потенциальный путь сотворить корягу, и что это недостаток ДотНет?
H>Нападки были не в этой ветке, я говорю обобщая те, что слышал. Я не только так считаю, я еще и пример приводил
Здравствуйте, kuj, Вы писали:
___>>Выпить хочется — это по другой причине. А деструкторов в шарпе — нет. Есть финализаторы — а это огромная разница. Читать Рихтера.
kuj>Вообще-то есть... http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx
Понятие слово "деструктор" было взято из С++. В .Net CLR это несколько другое. Вобщем, читать Рихтера.
Здравствуйте, OCTAGRAM, Вы писали:
OCT>Вообще, в Borland оставлены ниточки, чтобы инициализировать "File" OCT>своими методами Read/Write/Flush/Close. Но на практике работают чаще с OCT>TStream, просто используют функции–форматтеры.
Не покажите как выглядит код с использованием TStream?
___>>>Выпить хочется — это по другой причине. А деструкторов в шарпе — нет. Есть финализаторы — а это огромная разница. Читать Рихтера.
kuj>>Вообще-то есть... http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx
___>Понятие слово "деструктор" было взято из С++. В .Net CLR это несколько другое. Вобщем, читать Рихтера.
Вообще-то не другое, а то же самое. Финализатор в C# называется деструктором. Вообщем, читать MSDN.
Здравствуйте, Mamut, Вы писали:
M>То есть, какой смысл писать: M>
M>MyInterface : Interface(IUnknown)
M>
M>если класс, реализующий MyInterface может спокойно похерить реализацию методов из IUnknown?
Он не может ее похерить. Никак. MyInterface наследует методы IUnknown. Единственное различие, что в Delphi QueryInterface возвращает только интерфейс, который явно записан в таблицу COM (или как оно там в Делфи реализовано), а кривость дельфового RTTI не дает получить информацию про предков интерфейса...
Во всяком случае именно так получается со слов хаттаба...
M>>если класс, реализующий MyInterface может спокойно похерить реализацию методов из IUnknown?
kuj>Он не может ее похерить. Никак. MyInterface наследует методы IUnknown. Единственное различие, что в Delphi QueryInterface возвращает только интерфейс, который явно записан в таблицу COM (или как оно там в Делфи реализовано), а кривость дельфового RTTI не дает получить информацию про предков интерфейса...
kuj>Во всяком случае именно так получается со слов хаттаба...
Здравствуйте, kuj, Вы писали:
___>>>>Выпить хочется — это по другой причине. А деструкторов в шарпе — нет. Есть финализаторы — а это огромная разница. Читать Рихтера.
kuj>>>Вообще-то есть... http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx
___>>Понятие слово "деструктор" было взято из С++. В .Net CLR это несколько другое. Вобщем, читать Рихтера.
kuj>Вообще-то не другое, а то же самое. Финализатор в C# называется деструктором. Вообщем, читать MSDN.
Вобщем-то другое и не тоже самое. С С++, судя по всему, ты не знаком. А толку от того что называется — только путаница. А в MSDN я и тебя сам могу послать. Слово Рихтер тебе о чем-то говорит?
H>>// Объект реализующий только IMyInterface
H>>TMyObject = Class(TObject, IMyInterface)
H>>...
H>>End;
H>>// Объект реализующий, и IUnknown, и IMyInterface
H>>TMyObject2 = Class(TObject, IUnknown, IMyInterface)
H>>...
H>>End;
H>>
H>>В этом примере, от объекта класса TMyObject ты не сможешь получить IUnknown несмотря на то, что IMyInterface наследован от него.
M>Все. Дельфи идет в лес семимильными шагами. Настолько испоганить идею наследования — это надо постараться.
Ничего не испоганено. Ты просто не понимаешь того, что критикуешь.
M>"Вот у вас наследование, но это не наследование". "Вот у вас цепочка предков, но вы можете забить на то, что обозначено в любом из их предков, кроме ближайшего". "Если я родитель класса, то класс обязан реализовывать мои методы, а если дед — то необязан"
M>О. Кстати. Последняя фраза очень четко показывает кривизну такой реализации. Почему класс обязан реализовывать только методы непосредственного предка, а не всех предков по цепочке? Куда подевались методы всех предков? Если мы расширяем базовый интерфейс, разве это не значит, что методы предков никуда не подевались?
Мамут, ну сколько можно повторять: понятие наследования интерфейсов не соотносится с понятием наследования классов. Наследование интерфейсов есть суть расширение декларации.
M>То есть, какой смысл писать: M>
M>MyInterface : Interface(IUnknown)
M>
M>если класс, реализующий MyInterface может спокойно похерить реализацию методов из IUnknown?
Здравствуйте, kuj, Вы писали:
G>>>Значит бага делфи, в на других языках тоже самое отлично работает. G>>>Более того, если бы такое не работало в принцибе, не работал бы COM вообще.
H>>Это не бага. Просто ты тут пытаешься натянуть свое видение на окружающий мир, а он многообразен.
kuj>Угу, это не бага. Это очередной ляп в реализации Делфи (если это вообще так и ты не вешаешь нам лапшу на уши).
Ты всегда можешь это проверить. У меня нет задачи расписать Delphi, чтоб в нее все повлюблялись
Здравствуйте, _d_m_, Вы писали:
___>>>>>Выпить хочется — это по другой причине. А деструкторов в шарпе — нет. Есть финализаторы — а это огромная разница. Читать Рихтера.
kuj>>>>Вообще-то есть... http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx
___>>>Понятие слово "деструктор" было взято из С++. В .Net CLR это несколько другое. Вобщем, читать Рихтера.
kuj>>Вообще-то не другое, а то же самое. Финализатор в C# называется деструктором. Вообщем, читать MSDN.
___>Вобщем-то другое и не тоже самое. С С++, судя по всему, ты не знаком. А толку от того что называется — только путаница. А в MSDN я и тебя сам могу послать. Слово Рихтер тебе о чем-то говорит?
Еще раз для тех, кто в танке: в С# и C++ .NET деструкторами называются финализаторы. Что тебе не понятно? Сложно открыть и прочитать MSDN? Или в Рихтере по-другому написано?
Или ты пытаешься сказать своим "слово Рихтер", что деструктор в управляемой среде и деструктор в native различаются? Ну так ясное дело различаются. Тем, что в управляемой среде момент вызова деструктора и порядок вызова деструкторов связных объектов недетерминированные.
Здравствуйте, hattab, Вы писали:
G>>>>Значит бага делфи, в на других языках тоже самое отлично работает. G>>>>Более того, если бы такое не работало в принцибе, не работал бы COM вообще.
H>>>Это не бага. Просто ты тут пытаешься натянуть свое видение на окружающий мир, а он многообразен.
kuj>>Угу, это не бага. Это очередной ляп в реализации Делфи (если это вообще так и ты не вешаешь нам лапшу на уши).
H>Ты всегда можешь это проверить.
Не могу.
H>У меня нет задачи расписать Delphi, чтоб в нее все повлюблялись