代码之家  ›  专栏  ›  技术社区  ›  Ian Boyd

德尔菲:什么时候重新引入隐藏祖先,什么时候向他们展示?

  •  5
  • Ian Boyd  · 技术社区  · 14 年前

    今天 最近在Stackoverflow上我了解到:

    supporting my main question dealing with constructors .


    更新:

    TComputer = class(TObject)
    public
       constructor Create(Teapot: string='');
    end;
    
    TCellPhone = class(TComputer)
    public
       constructor Create(Cup: Integer); overload; virtual;
       constructor Create(Cup: Integer; Teapot: string); overload; virtual;
    end;
    

    构造TCellPhone时,有3个构造函数可用:

    • 杯:整数
    • [茶壶:字符串='']

    问题:为什么 constructor(Teapot: string='') 没有被隐藏?


    现在我添加了第三个后代:

    TComputer = class(TObject)
    public
       constructor Create(Teapot: string='');
    end;
    
    TCellPhone = class(TComputer)
    public
       constructor Create(Cup: Integer); overload; virtual;
       constructor Create(Cup: Integer; Teapot: string); overload; virtual;
    end;
    
    TiPhone = class(TCellPhone)
    public
       constructor Create(Cup: Integer); override;
    end;
    

    TiPhone 可使用构造函数:

    • 杯:整数

    这可能是代码洞察中的一个bug,它向我展示了四个——但是当两个相同时,我怎么可能调用它们。


    再次使用原始代码:

    t计算机=类(TObject)
    公众的
    构造函数创建(Teapot:string='');
    
    TCellPhone=类(t计算机)
    构造函数创建(Cup:Integer);重载;虚拟;
    构造函数创建(Cup:Integer;Teapot:string);重载;虚拟;
    结束;
    

    已经知道了 TCellPhone 有三个构造器:

    • 杯子:整数;茶壶:字符串
    • [茶壶:字符串='']

    我该如何更改

    TNokia = class(TCellPhone)
    end;
    

    将只有两个构造函数:

    • 杯:整数
    • 杯子:整数;茶壶:字符串

    现在来看看 reintroduce 有四个构造函数(理想情况下只有两个 TComputer 以某种方式隐藏了它的祖先)。但即使我修不好 t计算机 ,我可以改变 电话 只有一个:

    TComputer = class(TObject)
    public
        constructor Create(Teapot: string='');
    end;
    
    TCellPhone = class(TComputer)
    public
        constructor Create(Cup: Integer); overload; virtual;
        constructor Create(Cup: Integer; Teapot: string); overload; virtual;
    end;
    
    TiPhone = class(TCellPhone)
    public
        constructor Create(Cup: Integer); reintroduce;
    end;
    

    现在 只有一个构造函数:

    重新引入通常仅用于抑制有关隐藏的警告 事实上的 祖先。在这种情况下:

    Create(Teapot: string = '')
    

    不是虚拟的-但我仍然可以使用重新引入来隐藏它。


    现在 ,如果我将另一个重载添加到 电话 :

    TiPhone = class(TCellPhone)
    public
       constructor Create(Cup: Integer); reintroduce; overload;
       constructor Create(Handle: String); overload;
    end;
    

    • TiPhone.创建(7) (二);
    • TiPhone.创建(“粉色”);

    如你所见,我正在努力理解

    • 当有东西藏起来的时候
    • 如何隐藏
    4 回复  |  直到 7 年前
        1
  •  7
  •   Rob Kennedy    14 年前

    你不用 reintroduce 重新引入 抑制 警告 当祖先类的方法(被隐藏的方法)是虚拟的时,Delphi会提出这个问题。

    如果后代的方法 重写 祖先的,那它就不藏了。对祖先方法的调用被路由到后代的方法。

    如果后代的方法 祖先的,那么它也不会隐藏。两个都可以打电话。

        2
  •  1
  •   Community CDub    7 年前

    编辑: 我收回我的主张 “你什么都没隐瞒” . 我想我不太明白躲在这里的意思。我问过 quesiton 关于这个。

    更新:
    基于 answer 我得到了,我想重新表述我的答案:因为 TComputer.Constructor TCellPhone

        3
  •  1
  •   Ken Bourassa    14 年前

    好吧,在重载方法/构造函数的类中,似乎不能隐藏该方法/构造函数。我带着一个小小的“黑客”来设法把构造器从计算机中隐藏起来

      TComputer = class(TObject)
      public
          constructor Create(Teapot: string='');
      end;
    
      THackComputer = class(TComputer)
      public
        constructor Create(Cup : Integer);virtual;
      end;
    
      TCellPhone = class(THackComputer)
      public
          constructor Create(Cup: Integer); overload; override;
          constructor Create(Cup: Integer; Teapot: string); overload; virtual;
      end;
    
      TiPhone = class(TCellPhone)
      public
        constructor Create(Cup: Integer); reintroduce; virtual;
      end;
    

    在这个例子中,TiPhone只有一个构造函数可用。但它确实打破了多态性(这是向TCellPhone隐藏第二个构造函数所付出的代价)。我想知道是否有人找到了一种不破坏多态性的方法。

        4
  •  0
  •   Community CDub    7 年前

    我想把这个作为罗布·肯尼迪的回答的评论,但既然我不能,我就来。。

    只是因为你没有。

    如果我把祖先藏起来,为什么没有警告?我没有重新介绍。

    你看到了你没有隐瞒任何事情的证据。你检查过的3个可用的构造器就是证据。

    我想把我的想法放在如何隐藏上,但我同意塞尔塔克的观点,首先我要知道你对隐藏的定义是什么。

    编辑: 我刚看了你提到的帖子,我想你误解了这些概念。这是我的简短解释。

    reintroduce is used to hide ancestor constructors

    reintroduce is used to show ancestor constructors

    在那篇文章的回答中,重载关键字使祖先的构造函数仍然可用。

    另外,针对伊恩在以下评论中提出的问题:

    1. 隐藏具有特定名称的祖先构造函数
    2. 在子代中具有多个具有相同特定名称的构造函数。

    虽然它们看似简单的问题,但仔细一看就会立刻让你觉得它们的性质完全相反。问题1希望隐藏方法/构造函数,而问题2希望不仅显示一个方法/构造函数,而且显示多个方法/构造函数。所以如果你把它们混在一起 一步到位 ,他们肯定会互相取消。难怪他们会让你头痛。。。:)

    解决这两个问题的基本原则不是一步到位。这意味着我们需要一个中间类来解决问题1,并在该中间类的后代中执行重载。像这样的:

    type
      TComputer = class(TObject)
      private
        FCaller: TConstructorCaller;
      public
         constructor Create(Teapot: string=''); virtual;
    
         property Caller: TConstructorCaller read FCaller;
      end;
    
      TBaseCellphone=class(TComputer)
        constructor Create(Cup: Integer); virtual;
      end;
    
      TCellPhone = class(TBaseCellphone)
      protected
      public
        constructor Create(Cup: Integer); overload; override;
        constructor Create(Cup: Integer; Teapot: string); overload; virtual;
      end;
    
      TiPhone = class(TCellPhone)
      public
        constructor Create(Cup: Integer); reintroduce; overload;
        constructor Create(Handle: String); reintroduce; overload;
      end;
    

    在此处使用重载关键字,否则将取消隐藏。现在,在隐藏完成之后,现在可以在重载关键字的子代中自由地发送垃圾邮件,以获得具有相同名称的多个构造函数。

       TCellPhone.Create('My Teapot');