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

    Это понятно, хочется понять от чгео так сделано: просто так, или есть принципиально непреодолимые трудности сделать это на этапе компиляции в дельфи.
  • KSergey © (15.01.09 09:52) [21]
    > Anatoly Podgoretsky ©   (15.01.09 09:47) [18]
    > Откуда, да нет этого файла у программиста, он по заказу  пишет, а BPL большой секрет.

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

    Как мешает полиморфизм - я так же до сих пор не понимаю (кроме переменных типа ссылки на класс).
  • DrPass © (15.01.09 10:03) [22]

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

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

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


    Это не отлавливается. Если
    функция принимает параметр SomeClass* a;
    И делает вызов абстрактого метода.
    Как она может узнать какого он кокретно класса. Никак особенно, если объект создается вне, например в DLL.
  • Григорьев Антон © (15.01.09 10:11) [24]
    Это связано с наличием в Delphi метаклассов и виртуальных конструкторов. Из-за этого не всегда на этапе компиляции можно решить, конструктор какого именно класса вызывается - с абстрактными методами, или его потомка, в котором они перекрыты. А раз 100%-ый отлов всё равно невозможен, разработчики Delphi решили не париться с этим вообще и отлавливать всё только в run-time.
  • Григорьев Антон © (15.01.09 10:14) [25]

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

    Это здесь не при чём. Ошибка компилятора, по идее, должна возникать при попытке вызова конструктора для класса, содержащего абстрактные методы. Т.е. она должна возникать на строке a := TClassWithAbstractMethods.Create. Но, как я уже сказал, не всегда при компиляции возможно определить, конструктор какого класса будет вызван.
  • oxffff © (15.01.09 10:16) [26]
    > KSergey ©   (15.01.09 09:42) [16]
    > > SomeClass* a;
    > > a*.SomeAbstractMethod();
    >
    > Так не бывает. Пропущено собственно создание экземпляра
    > объекта (new), как раз там это легко отлавливается в С++.
    >

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

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

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


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

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

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

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

    Спасибо, похоже в этом и есть единственная причина, я тоже так думаю.
  • oxffff © (15.01.09 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 © (15.01.09 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 © (15.01.09 10:52) [31]
    чета все перемешано.
    В C++ если ф-ция принимает указатель на абстрактный класс - беды с этим нет и даже вызывает абстрактный метод - беды в этом нет, т.к. все равно никто не сможет передать ей указатель на класс с абстрактным методом, т.к. сконструировать такой класс (хоть ан стеке, хоть на куче) невозможно.

    Потому я и говорю, что DLL тут ваще ни при делах.
  • oxffff © (15.01.09 10:55) [32]

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


    Это вопрос идеалогии разрешать или не разрешать создание классов с абстрактными методами.
  • Григорьев Антон © (15.01.09 10:56) [33]

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

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

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

    А смысл? Всё равно это проверка не во время компиляции.
  • oxffff © (15.01.09 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 © (15.01.09 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 © (15.01.09 11:22) [36]
    > oxffff ©   (15.01.09 11:02) [34]

    Прекольно, не ведал.
  • Alkid © (15.01.09 12:26) [37]

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

    Я, вот, одного не понимаю - какой смысл разработчику создавать экземпляр класса с абстрактными методами? Мне бы очень хотелось бы узнать прецеденты, где какие-нибудь архитектурные задачи решались через создание экземпляров абстрактных классов. Пока же я твёрдо убеждён, что сама возможность так делать - зло.
  • Ega23 © (15.01.09 12:35) [38]

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


    1. От незнания (вопросов про "создание TStrings" за 5 лет я видел штук 50)
    2. От не обращания внимания на warnings
  • XentaAbsenta © (15.01.09 12:44) [39]
    Это не вопрос идеалогии, это вопро здравого смысла. Если в классе присутствуют абстрактные методы, то инстанцировать класс нельзя, потому, что это ведёт к неминуемым ошибкам, тоже самое и с непереопределёнными абстрактными методами. По Моему Космически Невероятно Мега-Супер Скромному Мнению компилятор должен в таких случаях требовать от программиста посавить модификатор abstact в определении класса и ни при каких обстоятельствах не позволять инстанцировать класс даже через ссылку на класс, которая вполне может тоже может нести в себе аттрибуты класса.
    А ошибки времени выполнения отлавливать и исправлять куда сложнее нежели ошибки компиляции.
 
Конференция "Прочее" » непереопределённые обстрактные методы
Есть новые Нет новых   [134453   +31][b:0][p:0.001]