На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

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


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Наследование перегружаемых методов
    Если я в родительском классе объявлю метод с некоторым именем и в дочернем классе объявлю метод с тем же именем (но с другими параметрами), то метод из родительского класса будет недоступен (не унаследуется):
    ExpandedWrap disabled
      type
        TX = class
          procedure Z;
        end;
       
        TY = class(TX)
          procedure Z(I: Integer);
        end;
       
      procedure TX.Z;
      begin
      end;
       
      procedure TY.Z(I: Integer);
      begin
      end;
       
      var Y: TY;
      begin
        Y := TY.Create;
        Y.Z  // Not enough actual parameters.
      end.

    Но! Если дочерний метод будет перегружен (например, для того, чтобы сделать 2 варианта вызова), то и родительский унаследуется тоже!
    ExpandedWrap disabled
      type
        TX = class
          procedure Z;
        end;
       
        TY = class(TX)
          procedure Z(I: Integer); overload;
          procedure Z(S: String); overload;
        end;
       
      procedure TX.Z;
      begin
      end;
       
      procedure TY.Z(I: Integer);
      begin
      end;
       
      procedure TY.Z(S: String);
      begin
      end;
       
      var Y: TY;
      begin
        Y := TY.Create;
        Y.Z  // Well done!
      end.

    А я не хочу, чтобы родительский метод наследовался! :wall:
    Можно ли это сделать? Желательно, чтобы это работало, начиная с Delphi7...

    Добавлено
    И вообще, можно ли как-то обозначить в дочернем классе, какие методы нужно наследовать, а какие нет (если точнее, то меня даже больше волнует, какие из них будут public, а какие private/protected... в предыдущем вопросе имеется в виду то же самое).
      ну а что мешает изначально у родителя метод сделать приватным, а у дочернего публичные методы?

      по умолчанию все идут publiched (если мне память не изменяет)
        Цитата ViktorXP @
        ну а что мешает изначально у родителя метод сделать приватным, а у дочернего публичные методы?
        Мешает то, что я не смогу использовать родительский метод.
        Суть в том, что в методе родительского класса выполняется одна работа, а в дочернем - другая. Поэтому, если из дочернего класса будет вызван метод родителя, он сработает не в кассу. Но доступными должны быть и те методы, и другие, но только в своих классах.
          Цитата Jin X @
          А я не хочу, чтобы родительский метод наследовался!

          наверное будет куда правильнее сделать два наследника. с разными реализациями.
          или переделать логику на интерфейсы.
          пс. просто без общей идеи зачем это сложно судить что конкретно ты хочешь получить.


          пс. то что метод виден это не бага. подобное поведение задокументировано Overloading_Methods
          пс.пс. по своей практике скажу что подобное поведение логично правильное. так как тебе чаще нужно добавить однодоменную функцию, а не заменить (если ты конечно не перегружаешь)
            Так, я и не говорю, что это баг :)
            Просто есть полиморфизм, который как раз заключается в том, чтобы при одинаковых именах иметь разную реализацию у предка и наследника.
            Бывает же такое, что у наследника какая-то функция (метод) уже не нужна, для него это рудимент.
            Но как я понял, единственный вариант - это объявить метод таким же образом и реализовать его в теми параметрами, что у предка.
            Странно, что такого функционала нет.
              Посмотри, как сделано в VCL. Базовый класс называется TCustom*, и большую часть методов и полей имеет protected. А для юзания наследуется T*, который просто открывает нужные члены класса.

              Добавлено
              Да, и простые protected/private видны внутри того же модуля, чтобы отключить эту видимость - надо добавить strict
                Цитата Fr0sT @
                Посмотри, как сделано в VCL. Базовый класс называется TCustom*, и большую часть методов и полей имеет protected. А для юзания наследуется T*, который просто открывает нужные члены класса.
                С property, допустим, понятно. А что делать с методами? Как их "открыть"?
                Можно, конечно, сделать так:
                ExpandedWrap disabled
                  type TCustomBlaBla = class
                    protected
                      procedure DoSomething;
                    end;
                   
                    TBlaBla = class(TCustomBlaBla)
                    public
                      procedure Something;
                    end;
                   
                  procedure TBlaBla.Something; inline;
                  begin
                    DoSomething
                  end;
                Но это всё равно извращение, ИМХО...
                Тем более, если потом я захочу унаследовать что-то от TBlaBla, опять та же проблема возникнет...

                Цитата Fr0sT @
                Да, и простые protected/private видны внутри того же модуля, чтобы отключить эту видимость - надо добавить strict
                Мне нужна видимость не внутри, а снаружи как раз-таки...
                  Тьфу блин, совсем ты запутал своими тредами, уже и тут начал подвох искать.

                  ExpandedWrap disabled
                          TX = class
                          strict private
                            procedure Z;
                          end;
                     
                    ...
                     
                          Y.Z;  // [DCC Error] Unit1.pas(843): E2389 Protected member 'TX.Z' is inaccessible here
                    ExpandedWrap disabled
                      type
                        TX = class
                          procedure Z;
                        end;
                       
                        TY = class(TX)
                          procedure Z(I: Integer); overload;
                          procedure Z(S: String); overload;
                        end;
                       
                      procedure TX.Z;
                      begin
                      end;
                       
                      procedure TY.Z(I: Integer);
                      begin
                      end;
                       
                      procedure TY.Z(S: String);
                      begin
                      end;
                       
                      var Y: TY;
                          X: TX;
                       
                      begin
                        Y := TY.Create;
                        Y.Z;  // допустим у тебя всё получилось и данная конструкция не работает
                       
                        // а если мы сделаем так?
                        TX(Y).Z;
                        // или так?
                        X:=Y;
                        X.Z;
                      end.
                      Shaggy, иии???
                      Таким образом можно запустить любой родительский метод, причём тут это?
                      Мне это нужно не для того, чтобы злостный программист не смог запустить этот метод никакими ухищрениями и кулхацкерском, а чтобы просто убрать метод из области нормальной видимости. Чтобы при написании Y.Z выводилась ошибка, что мол "фуцк офф, нот инаф акшуал параметерс", чувак. Т.е. именно в потомке заменить Z на Z(I) и Z(S), убрав Z. А так-то понятно, что можно и ShowModal попытаться запустить для TList или узнать его ThreadID :D

                      Цитата Fr0sT @
                      Тьфу блин, совсем ты запутал своими тредами, уже и тут начал подвох искать.
                      Какой подвох? :huh:
                      Мне надо сделать так, чтобы у предка TX был доступен метод (ИЗВНЕ!!!) Z, а у потомка TY - только Z(I) и Z(S), но не Z.
                      А ты приводишь код, в котором даже TX.Z не будет доступен вообще. Зачем??? :facepalm: :)
                        Цитата Jin X @
                        Таким образом можно запустить любой родительский метод, причём тут это?
                        Мне это нужно не для того, чтобы злостный программист не смог запустить этот метод никакими ухищрениями и кулхацкерском, а чтобы просто убрать метод из области нормальной видимости. Чтобы при написании Y.Z выводилась ошибка, что мол "фуцк офф, нот инаф акшуал параметерс", чувак. Т.е. именно в потомке заменить Z на Z(I) и Z(S), убрав Z. А так-то понятно, что можно и ShowModal попытаться запустить для TList или узнать его ThreadID

                        никаких хаков тут нет и твоё желание невыполнимо.

                        убрать что-либо из интерфейса предка в потомке нельзя.

                        overload разрешает существование одноимённых (всех) методов.

                        можно скрыть метод предка объявив одноимённый метод в потомке.
                        ооп тут нипричём, можно описать, например, IntToStr в своём модуле и скрыть объявление стандартной
                        и если на уровне модулей всё разрешается с помощью qualified name и/или overload, то для объектов нужно приведение к предку

                        кроме того, ты можешь забыть про своё "гениальное" архитектурное решение и написать примерно так:
                        ExpandedWrap disabled
                          var Y: TY;
                          ...
                          procedure Something(X:TX);
                          begin
                            X.Z;
                          end;
                          ...
                          Something(Y);
                          Цитата Shaggy @
                          кроме того, ты можешь забыть про своё "гениальное" архитектурное решение и написать примерно так:
                          Здесь (в твоём примере) будет выполнен метод предка, а не потомка. Т.е. выполнен код X.Z (если он не виртуальный). Не надо путать.
                          Одноимённый метод предка можно скрыть объявлением метода с тем же именем... Если только он не overload(!) В этом-то и весь нюанс.
                          Но я уже понял, что нужного мне механизма нет. Значит, нужно "идти другим путём". Что-то вроде описанного выше #7
                            Цитата Jin X @
                            Мне надо сделать так, чтобы у предка TX был доступен метод (ИЗВНЕ!!!) Z, а у потомка TY - только Z(I) и Z(S), но не Z.

                            Вот сформулировал бы по-нормальному задачу с самого начала - и не было бы недопониманий.
                            Твоей хотелке только интерфейсы помогут. Либо перекраивать структуру объектов, наследуя TX с методом Z и TY с методами Z(byte), Z(string) от общего TW, у которого Z нет вообще.
                              Цитата Jin X @
                              Одноимённый метод предка можно скрыть объявлением метода с тем же именем... Если только он не overload(!) В этом-то и весь нюанс.

                              Поэтому, если очень нужно, то можно использовать финт ушами - создать промежуточный класс TXY, в котором объявить один из методов, например Z(I:integer) без overload. А в TY добавить нужные overload-ы. Не удобно, конечно, но что поделаешь, раз "нужного механизма нет".
                                leo, понятно. Да, вариант тоже не фонтан.
                                Я вот думал, что можно будет его спрятать в private, но... он не прячется, а создаётся ещё один метод с таким же именем (только private), но родительский метод всё равно виден (извне).

                                Fr0sT, не знаю, как ещё нормальнее формулировать? :)
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0460 ]   [ 17 queries used ]   [ Generated: 25.04.24, 10:22 GMT ]