Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2009.03.15;
Скачать: [xml.tar.bz2];

Вниз

непереопределённые обстрактные методы   Найти похожие ветки 

 
XentaAbsenta ©   (2009-01-15 03:28) [0]

Скажите, почему делфя позволяет скомпилить прект если не все абстрактные методы переопределены, более того - она даже не матерится на это.


 
Германн ©   (2009-01-15 03:49) [1]


> XentaAbsenta ©   (15.01.09 03:28)
>
> Скажите, почему делфя позволяет скомпилить прект если не
> все абстрактные методы переопределены, более того - она
> даже не матерится на это.
>

А что в этом плохого?


 
Германн ©   (2009-01-15 03:53) [2]

В код исполняемой программы попадёт лишь то, что реально вызывается.


 
XentaAbsenta ©   (2009-01-15 04:05) [3]

плохого в этом то, что я периодически получаю EAbstractError, при том что вместо этого я бы просто не скомпилил проект


 
Котик Б   (2009-01-15 08:53) [4]

А вот интересно - если вы периодически получаете AV, обращаясь к нераспределённым объектам - тоже Делфай виновата ?


 
oxffff ©   (2009-01-15 09:07) [5]


> XentaAbsenta ©   (15.01.09 03:28)  
> Скажите, почему делфя позволяет скомпилить прект если не
> все абстрактные методы переопределены, более того - она
> даже не матерится на это.


Потому, что в момент компиляции полиморфного вызова тип объекта установить невозможно, из-за ссылочной семантики объекта.
Если бы этого небыло, тогда проблем было бы гораздо больше.
Например твой проект определяет контракты (абстрактные классы), подключает внешние реализации(DLL) и вызывает их через контракт базовый абстрактного класса. Если бы этого не было, то такой проект невозможно было бы сделать.


 
Anatoly Podgoretsky ©   (2009-01-15 09:07) [6]

> XentaAbsenta  (15.01.2009 3:28:00)  [0]

Потому что они могут быть недоступны на момент компиляции, например в BPL


 
KSergey ©   (2009-01-15 09:10) [7]

Я вот точно не знаю, но вероятно штука вот в чем.
В С++ нельзя создать экземпляр класса с заранее неизвестным типом, язык таков. Потому все на уровне компилятора можно отловить.

В дельфи - можно, через классовую переменную. Потому и нельзя на этапе компиляции в общем случае определить.
Впрочем, для явного выгова TAbstractClass.Create() вроде можно было бы и добавить compile-magic, но не сделали, видимо некритично.


 
oxffff ©   (2009-01-15 09:13) [8]


> KSergey ©   (15.01.09 09:10) [7]


Из-за разной семантики объекта

SomeClass* a;
a.SomeAbstractClass();

НО не

SomeClass b;
b.SomeAbstractClass();   <- попытка вызвать у известного типа.


 
KSergey ©   (2009-01-15 09:21) [9]

> Anatoly Podgoretsky ©   (15.01.09 09:07) [6]
> Потому что они могут быть недоступны на момент компиляции,  например в BPL

Я чета недогоняю этот нюанс: декларация же полностью доступна компилятору в любом случае, а в ней все есть.
Что я непонимаю?


 
KSergey ©   (2009-01-15 09:25) [10]

> oxffff ©   (15.01.09 09:13) [8]
> НО не
>
> SomeClass b;
> b.SomeAbstractClass();   <- попытка вызвать у известного типа.

Можно еще раз, для тупых, плиз
Я честно не понял семантики используего языка. Это типа С++? Тогда как понять a.SomeAbstractClass() ? Что это за метод? (предупреждаю, с реализацией фабрик на С++ не сталкивался, может от того непонимание)

Тип уже указан, SomeClass. И экземпляр уже сконструирован. А что за SomeAbstractClass тогда??


 
oxffff ©   (2009-01-15 09:26) [11]


> KSergey ©   (15.01.09 09:21) [9]


[8].

SomeClass* a;
a.SomeAbstractClass();

Как компилятор может догадаться, что вызов происходит будет только у абстрактого класса?


 
KSergey ©   (2009-01-15 09:31) [12]

> oxffff ©   (15.01.09 09:26) [11]
> SomeClass* a;
> a.SomeAbstractClass();

Я никак не могу понять этой записи: создан экземпляр указателя, и вдруг к нему идет обращение через точку, какой-то метод вызывается... Это какой-то smart pointer?


 
KSergey ©   (2009-01-15 09:32) [13]

хоты нет, это чистый указатель.... не понимаю


 
oxffff ©   (2009-01-15 09:33) [14]


> KSergey ©   (15.01.09 09:25) [10]
> Можно еще раз, для тупых, плиз


Ну не нужно скромничать. :)

Указателю на экземпляр можно присвоить экземпляр производных типов.

SomeClass* a;
a*.SomeAbstractMethod();

Поэтому установить нарушение можно в случае полного анализа полного потока программы. Что достаточно сложно.
А для подключаемых DLL с подклассами сделать невозможно.
Поэтому нарушение установить нельзя.

В сам экземпляр можно присвоить бинарно только экземпляр идентичного типа.

SomeClass b;
b.SomeAbstractMethod();  

Здесь b может быть только SomeClass.
Поэтому установить нарушение можно сразу.


 
oxffff ©   (2009-01-15 09:36) [15]


> oxffff ©   (15.01.09 09:33) [14]


У Dеlphi случай как раз SomeClass* a;


 
KSergey ©   (2009-01-15 09:42) [16]

> SomeClass* a;
> a*.SomeAbstractMethod();

Так не бывает. Пропущено собственно создание экземпляра объекта (new), как раз там это легко отлавливается в С++.


 
Alkid ©   (2009-01-15 09:46) [17]

Что-то вас в дебри понесло.
Вся штука в том, что Дельфи позволяет создавать экземпляры абстрактных классов, когда как C++, C#, Java - нет.


 
Anatoly Podgoretsky ©   (2009-01-15 09:47) [18]

> KSergey  (15.01.2009 9:21:09)  [9]

Откуда, да нет этого файла у программиста, он по заказу пишет, а BPL большой секрет.
Да и про полиморфизм не стоит забывать.


 
Anatoly Podgoretsky ©   (2009-01-15 09:49) [19]

Сообственно беспокоиться особо не о чем, будет ошибка в ран-тайм. Кроме этого еще много вещей, которые разрешаются в ран-тайм.


 
KSergey ©   (2009-01-15 09:50) [20]

> Alkid ©   (15.01.09 09:46) [17]
> Вся штука в том, что Дельфи позволяет создавать экземпляры
> абстрактных классов, когда как C++, C#, Java - нет.

Это понятно, хочется понять от чгео так сделано: просто так, или есть принципиально непреодолимые трудности сделать это на этапе компиляции в дельфи.


 
KSergey ©   (2009-01-15 09:52) [21]

> Anatoly Podgoretsky ©   (15.01.09 09:47) [18]
> Откуда, да нет этого файла у программиста, он по заказу  пишет, а BPL большой секрет.

С BPL не работал, но у меня большое сомнение вызывает возможность вызова несуществующего метода у класса, описанного в BPL. А раз так - значит и про абстрактность вроде можно было добавить битик.

Как мешает полиморфизм - я так же до сих пор не понимаю (кроме переменных типа ссылки на класс).


 
DrPass ©   (2009-01-15 10:03) [22]


> С BPL не работал, но у меня большое сомнение вызывает возможность
> вызова несуществующего метода у класса, описанного в BPL

"Рассказ не читал, но крайне не одобряю" (с) :)
Речь идет о том, что в Delphi реализовано связывание на уровне классов. Т.е. есть абстрактный класс, который описан в одном программном модуле, его морда выставлена в таблице импорта этого модуля. А его потомок с реализацией абстрактных методов может находиться совсем в другом программном модуле. Поскольку оба исполняемых файла компилируются раздельно, Delphi понятия не имеет, где находится (и находится ли вообще) реализация, и вполне справедливо оставляет эту проблему на совести программиста


 
oxffff ©   (2009-01-15 10:06) [23]


> KSergey ©   (15.01.09 09:42) [16]
> > SomeClass* a;
> > a*.SomeAbstractMethod();
>
> Так не бывает. Пропущено собственно создание экземпляра
> объекта (new), как раз там это легко отлавливается в С++.
>


Это не отлавливается. Если
функция принимает параметр SomeClass* a;
И делает вызов абстрактого метода.
Как она может узнать какого он кокретно класса. Никак особенно, если объект создается вне, например в DLL.


 
Григорьев Антон ©   (2009-01-15 10:11) [24]

Это связано с наличием в Delphi метаклассов и виртуальных конструкторов. Из-за этого не всегда на этапе компиляции можно решить, конструктор какого именно класса вызывается - с абстрактными методами, или его потомка, в котором они перекрыты. А раз 100%-ый отлов всё равно невозможен, разработчики Delphi решили не париться с этим вообще и отлавливать всё только в run-time.


 
Григорьев Антон ©   (2009-01-15 10:14) [25]


> oxffff ©   (15.01.09 10:06) [23]
> Это не отлавливается. Если
> функция принимает параметр SomeClass* a;
> И делает вызов абстрактого метода.
> Как она может узнать какого он кокретно класса. Никак особенно,
>  если объект создается вне, например в DLL.

Это здесь не при чём. Ошибка компилятора, по идее, должна возникать при попытке вызова конструктора для класса, содержащего абстрактные методы. Т.е. она должна возникать на строке a := TClassWithAbstractMethods.Create. Но, как я уже сказал, не всегда при компиляции возможно определить, конструктор какого класса будет вызван.


 
oxffff ©   (2009-01-15 10:16) [26]

> KSergey ©   (15.01.09 09:42) [16]
> > SomeClass* a;
> > a*.SomeAbstractMethod();
>
> Так не бывает. Пропущено собственно создание экземпляра
> объекта (new), как раз там это легко отлавливается в С++.
>

Метакласс здесь совершенно непричем.
Еще раз повторяю, если объект размещен на стеке,
то никакой полиморфизм не нужен, поскольку объект известного одного типа(его тип известен и он не может быть другим)
Поскольку на стеке объект размещен известного типа, и забиндить методы можно напрямую минуя VMT.

Если объект размещен в куче, соответственно обращение к нему через идет указатель. А указатель на тип может принимать и указатели на дочерние классы, в этом и заключается смысл полиморфизма. Принимать разные типы, и делать единый вызов.
Поэтому в точке вызова невозможно узнать тип, за исключением тех случаев
когда new перед ней. Однако если объект создается вне и передается указатель, то узнать тип(а соответственно корректность вызова) невозможно.
Конечно технически можно просто проверить, опросив RTTI объекта IsAbstractMethodImplemented. Однако здесь дополнительные расходы.
Нужен единый подход к вызову через указатель. Выбрали разрешено, без лишних проверок. В Delphi добавили просто информативные stub абстрактные методы.


 
oxffff ©   (2009-01-15 10:20) [27]


> Григорьев Антон ©   (15.01.09 10:11) [24]
> Это связано с наличием в Delphi метаклассов и виртуальных
> конструкторов. Из-за этого не всегда на этапе компиляции
> можно решить, конструктор какого именно класса вызывается
> - с абстрактными методами, или его потомка, в котором они
> перекрыты. А раз 100%-ый отлов всё равно невозможен, разработчики
> Delphi решили не париться с этим вообще и отлавливать всё
> только в run-time.


Согласен.


 
KSergey ©   (2009-01-15 10:22) [28]

> oxffff ©   (15.01.09 10:06) [23]
> И делает вызов абстрактого метода.
> Как она может узнать какого он кокретно класса.

А в функции и не надо отлавливать. Надо на создании отлавливать, т.к. это однозначно. Тогда и вызвать функцию с абстрактным классом ни у кого просто не получится.

А зачем все на эти DLL насели - мне вообще не понятно. Ни при чем оно тут совершенно.

> Григорьев Антон ©   (15.01.09 10:11) [24]

Спасибо, похоже в этом и есть единственная причина, я тоже так думаю.


 
oxffff ©   (2009-01-15 10:27) [29]


> Григорьев Антон ©   (15.01.09 10:14) [25]
>
> > oxffff ©   (15.01.09 10:06) [23]
> > Это не отлавливается. Если
> > функция принимает параметр SomeClass* a;
> > И делает вызов абстрактого метода.
> > Как она может узнать какого он кокретно класса. Никак
> особенно,
> >  если объект создается вне, например в DLL.
>
> Это здесь не при чём. Ошибка компилятора, по идее, должна
> возникать при попытке вызова конструктора для класса, содержащего
> абстрактные методы. Т.е. она должна возникать на строке
> a := TClassWithAbstractMethods.Create. Но, как я уже сказал,
>  не всегда при компиляции возможно определить, конструктор
> какого класса будет вызван.


С этим не согласен. Поэтому [26].
По причине, того разрешать или не разрешать создание экземпляров классов с абстракными методыми.
На этот вопрос ответа однозначного нет.
Это вопрос идеалогии.
И быть не может.

Рассмотрим класс А с некой фунциональностью и одним абстрактным методом. И его наследником B с перекрытым методом и расширенным других функионалом.
Зачем мне создавать B(дополнительные затраты), если мне нужна фунциональность A без абсрактного класса.
Одни скажут неправильная декомпозции, другие скажут проблема глубокой декомпозции и эффективности.
Это вопрос идеалогии.


 
oxffff ©   (2009-01-15 10:35) [30]


> Григорьев Антон ©   (15.01.09 10:14) [25]
>
> > oxffff ©   (15.01.09 10:06) [23]
> > Это не отлавливается. Если
> > функция принимает параметр SomeClass* a;
> > И делает вызов абстрактого метода.
> > Как она может узнать какого он кокретно класса. Никак
> особенно,
> >  если объект создается вне, например в DLL.
>
> Это здесь не при чём. Ошибка компилятора, по идее, должна
> возникать при попытке вызова конструктора для класса, содержащего
> абстрактные методы. Т.е. она должна возникать на строке
> a := TClassWithAbstractMethods.Create. Но, как я уже сказал,
>  не всегда при компиляции возможно определить, конструктор
> какого класса будет вызван.


Я тут подумал и решил, что все же не согласен.
Это совершенно не проблемма.
Достаточно в конструкторах абстрактных классов в Delphi вставить проверку.
if DL = 1 then raise Exception.create("AttemptTocreateAbstractClass").
Думаю до этого они догадаться точно смогли.
И создавайте хоть напрямую, хоть через метаклассы.

Думаете они тоже не дога


 
KSergey ©   (2009-01-15 10:52) [31]

чета все перемешано.
В C++ если ф-ция принимает указатель на абстрактный класс - беды с этим нет и даже вызывает абстрактный метод - беды в этом нет, т.к. все равно никто не сможет передать ей указатель на класс с абстрактным методом, т.к. сконструировать такой класс (хоть ан стеке, хоть на куче) невозможно.

Потому я и говорю, что DLL тут ваще ни при делах.


 
oxffff ©   (2009-01-15 10:55) [32]


> KSergey ©   (15.01.09 10:52) [31]
> чета все перемешано.
> В C++ если ф-ция принимает указатель на абстрактный класс
> - беды с этим нет и даже вызывает абстрактный метод - беды
> в этом нет, т.к. все равно никто не сможет передать ей указатель
> на класс с абстрактным методом, т.к. сконструировать такой
> класс (хоть ан стеке, хоть на куче) невозможно.
>
> Потому я и говорю, что DLL тут ваще ни при делах.


Это вопрос идеалогии разрешать или не разрешать создание классов с абстрактными методами.


 
Григорьев Антон ©   (2009-01-15 10:56) [33]


> oxffff ©   (15.01.09 10:27) [29]

Просто здесь прозвучало "как в C++, Java, C#" - вот я и рассказал, как это было бы в Delphi, если бы было как в этих языках.

> oxffff ©   (15.01.09 10:35) [30]

А смысл? Всё равно это проверка не во время компиляции.


 
oxffff ©   (2009-01-15 11:02) [34]

В Delphi решили перенести этот выбор на разработчика.

A class type declaration has the form

type
  className = class [abstract | sealed] (ancestorClass)
     memberList  
  end;

If a class is marked sealed, then it cannot be extended through inheritance. If a class is marked abstract, then it cannot be instantiated directly using the Create constructor. An entire class can be declared abstract even if it does not contain any abstract virtual methods. A class cannot be both abstract and sealed.


 
oxffff ©   (2009-01-15 11:02) [35]


> Григорьев Антон ©   (15.01.09 10:56) [33]
>
> > oxffff ©   (15.01.09 10:27) [29]
>
> Просто здесь прозвучало "как в C++, Java, C#" - вот я и
> рассказал, как это было бы в Delphi, если бы было как в
> этих языках.
>
> > oxffff ©   (15.01.09 10:35) [30]
>
> А смысл? Всё равно это проверка не во время компиляции.


Смысл простой это вопрос идеалогии. [34]


 
KSergey ©   (2009-01-15 11:22) [36]

> oxffff ©   (15.01.09 11:02) [34]

Прекольно, не ведал.


 
Alkid ©   (2009-01-15 12:26) [37]


> oxffff ©   (15.01.09 11:02) [35]
>
> Смысл простой это вопрос идеалогии. [34]

Я, вот, одного не понимаю - какой смысл разработчику создавать экземпляр класса с абстрактными методами? Мне бы очень хотелось бы узнать прецеденты, где какие-нибудь архитектурные задачи решались через создание экземпляров абстрактных классов. Пока же я твёрдо убеждён, что сама возможность так делать - зло.


 
Ega23 ©   (2009-01-15 12:35) [38]


> какой смысл разработчику создавать экземпляр класса с абстрактными
> методами?


1. От незнания (вопросов про "создание TStrings" за 5 лет я видел штук 50)
2. От не обращания внимания на warnings


 
XentaAbsenta ©   (2009-01-15 12:44) [39]

Это не вопрос идеалогии, это вопро здравого смысла. Если в классе присутствуют абстрактные методы, то инстанцировать класс нельзя, потому, что это ведёт к неминуемым ошибкам, тоже самое и с непереопределёнными абстрактными методами. По Моему Космически Невероятно Мега-Супер Скромному Мнению компилятор должен в таких случаях требовать от программиста посавить модификатор abstact в определении класса и ни при каких обстоятельствах не позволять инстанцировать класс даже через ссылку на класс, которая вполне может тоже может нести в себе аттрибуты класса.
А ошибки времени выполнения отлавливать и исправлять куда сложнее нежели ошибки компиляции.


 
oxffff ©   (2009-01-15 12:51) [40]


> Alkid ©   (15.01.09 12:26) [37]
>
> > oxffff ©   (15.01.09 11:02) [35]
> >
> > Смысл простой это вопрос идеалогии. [34]
>
> Я, вот, одного не понимаю - какой смысл разработчику создавать
> экземпляр класса с абстрактными методами? Мне бы очень хотелось
> бы узнать прецеденты, где какие-нибудь архитектурные задачи
> решались через создание экземпляров абстрактных классов.
>  Пока же я твёрдо убеждён, что сама возможность так делать
> - зло.


Существуют алтернативные мнения. [29]
Задача инструмента предоставить выбор.



Страницы: 1 2 3 вся ветка

Форум: "Прочее";
Текущий архив: 2009.03.15;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.58 MB
Время: 0.091 c
15-1231734124
Slider007
2009-01-12 07:22
2009.03.15
С днем рождения ! 12 января 2009 понедельник


8-1191770086
яблочго
2007-10-07 19:14
2009.03.15
Установка палитры в TBitmap


15-1231254171
Palladin
2009-01-06 18:02
2009.03.15
Конструкция языка JavaScript


15-1231752808
Добежал
2009-01-12 12:33
2009.03.15
Хранение списка услуг


15-1231595981
Slider007
2009-01-10 16:59
2009.03.15
С днем рождения ! 6 января 2009 вторник





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский