【问题标题】:How to overload a function based on the result type?如何根据结果类型重载函数?
【发布时间】:2011-09-15 10:42:45
【问题描述】:

只是一个问题,我有:

myclass = class
public
  function Funct1: String;
  function Funct2: Integer;
end;

这让我出错了,所以我尝试了:

myclass = class
public
  function Funct1: String; overload;
  function Funct2: Integer; overload;
end;

但同样的问题; delphi 告诉我有相同的参数。 现在,我问,是否可以在模式下执行更多具有相同名称但输出不同的功能,例如示例? 非常感谢您的帮助。

更新

对不起,我做错了,不是funct1和funct2,而是funct1,所以:

myclass = class
public
  function Funct1: String; overload;
  function Funct1: Integer; overload;
end;

这样做,编译器会返回这个错误:

[DCC 错误] Project1.dpr(15): E2252 具有相同参数的方法“funct1”已存在 [DCC 错误] Project1.dpr(22): E2037 'funct1' 的声明与之前的声明不同

当然,我知道因为给出错误并且需要将名称更改为两个函数之一(因为我之前对此感到困惑)但我想知道是否有一些技巧或其他解决方案可以让这种情况没有错误。 再次感谢。

【问题讨论】:

  • 原则上编译器可以做你想做的事,在某些情况下。您的字符串和整数示例处理起来很简单。但该功能并未实现。
  • IMO,你试图完成的事情不会有用,会让你的代码更难维护,而且似乎有悖常理。

标签: delphi overloading delphi-xe2


【解决方案1】:

您可以将函数转换为带有var 参数的过程:

myclass = class
public
  procedure Funct1(var AResult: String); overload;
  procedure Funct1(var AResult: Integer); overload;
end;

【讨论】:

    【解决方案2】:

    首先,对于要重载的函数,它们必须命名相同。

    其次,这是不可能的。重载的函数必须有不同的参数。

    在您的情况下,编译器无法判断要调用哪个函数(假设两者都重命名为 Funct1):

    var
      v: Variant;
      mc: myclass;
    begin
      v := mc.Funct1;
    end;
    

    【讨论】:

    • +1 举例说明为什么重载不能单独区分结果类型。
    • “编译器无法判断”为什么不呢?编译器可以知道函数何时被调用并期待每种类型的结果。
    • 并非如此。考虑一下: var a: Variant; a := myclass.Funct1;
    【解决方案3】:

    您发布的内容没有意义。第一个示例应该可以顺利编译,因为函数有不同的名称Funct1Funct2

    只有当方法(或函数)具有相同的名称时才会出现问题。然后,通常情况下,overload 指令将是有序的,但 overload 不能仅根据返回值区分函数

    所以假设名称相同,您想要的就是不可能的。如果它们没有不同的参数签名,则无法重载这些函数。您可以只给它们起不同的名称,这无论如何都是可取的,因为它们显然做不同的事情。


    FWIW,您的问题存在缺陷,因为您显然没有发布您实际遇到问题的确切代码。请始终发布导致您的问题的确切代码,如果有错误消息,请始终发布确切的错误消息(通常可以使用通常的复制键击来复制它们,例如 Ctrl+C,即使在 IDE 的大多数部分或Delphi 中的消息对话框)。如果错误消息中有任何行号,请在您发布的源代码中指出这一点,因为我们并不总是拥有与您相同的行号。

    【讨论】:

    • 感谢您的回答,是的,我的意思是同名;抱歉之前我弄错了。
    • 请参阅行下部分:始终发布实际代码,直接从编辑器复制,而不是某种编造的代码,直接输入浏览器。
    【解决方案4】:

    如果你想重载具有不同返回类型的方法,只需添加一个具有默认值的虚拟参数以允许重载执行,但不要忘记参数类型应该不同所以重载逻辑作品例如:

    type    
        myclass = class
        public
          function Funct1(dummy: string = EmptyStr): String; overload;
          function Funct1(dummy: Integer = -1): Integer; overload;
        end;
    

    这样使用

    procedure tester;
    var yourobject : myclass;
      iValue: integer;
      sValue: string;
    begin
      yourobject:= myclass.create;
      iValue:= yourobject.Funct1(); //this will call the func with integer result
      sValue:= yourobject.Funct1(); //this will call the func with string result
    end;
    

    也不要忘记,这样你会遇到这个例子中的变体问题:

    procedure tester;
    var yourobject : myclass;
      vValue: variant;
    begin
      yourobject:= myclass.create;
      vValue:= yourobject.Funct1(); 
    end;
    

    直到你也实现了变体功能:

          function Funct1(dummy: Variant = Unassigned): Variant; overload;
    

    【讨论】:

    • 你在做什么很聪明,但是愚弄编译器从来都不是明智之举
    • 谢谢,我想......关于编译器愚弄问题,它实际上来自它自己的问题!因为我们从一开始就试图做的是根据结果类型重载一个函数,这意味着欺骗编译器,所以这就是你如何理解这个问题“我怎么能欺骗编译器来重载一个基于结果类型的函数结果类型?”,我的意思是这个问题值得这个答案,否则我只是使用了行为设计模式中的策略模式..这几乎在所有地方都使用,包括 VCL
    • 起初我认为这是一个不错的 hack。但vValue:= yourobject.Funct1() 不会在 Delphi 5 中编译。错误:Ambiguous overloaded call to 'Funct1'。也许这会在较新的版本中编译。我现在无法确认。
    • @kobik 我确认它适用于 Delphi 7 及更高版本
    【解决方案5】:

    如前所述,您不能按照自己的意愿去做。但是,您可以使用不同的名称(例如“AsInteger”或“AsString”)轻松实现每个函数。您的代码会更清晰,这通常是在 VCL 中完成的方式。

    TmyClass = class (TObject)
    public
      function AsString : string;
      function AsInteger : Integer;
    end;
    

    【讨论】:

    • 这取决于结果是相同值的不同表示。
    • 没错,但最初的问题是关于重载它们,在我看来这意味着它们都是相关的(因为它们没有参数,所以它们的结果必须是相关的)。无论如何,根据结果的含义命名函数,一切都很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-05
    • 2015-09-02
    • 2010-09-13
    相关资源
    最近更新 更多