所以很多语言都有这样的模式:
object = Create_Object().Set(1).Set(2).Set(3);
(我相信这起源于Smalltalk。)这是有效的,因为Set()
方法返回对其接收者的引用。
我可以在Ada做这样的事吗?
我尝试过的工作包括:
-- doesn't work because the returned object is a read-only copy of the receiver
function Set(self: in out Object) return Object;
-- doesn't work because I can't return an access to a local variable
function Set(self: in out Object) return access Object;
-- looks like it works until I realise that it's not a method, and isn't doing
-- dynamic dispatch [*]
function Set(self: access Object) return access Object;
可以这样做吗?
答案 0 :(得分:1)
我认为使用此配置文件的功能将为您完成这项工作:
function Set (Target : in Instance;
New_Item : in Integer) return Instance;
围绕该函数声明编写完整的包,我可以写:
Object := Set (1).Set (2).Set (3);
Object.Show;
并获得输出:
{1, 2, 3}
我已将完整的资源推送到http://repositories.jacob-sparre.dk/miscellaneous-ada-2005-examples/。
答案 1 :(得分:1)
你的第三个提议是正确的方法,当你输入" access"时,你实际上定义了一个原始操作。对于参数。下面是一个示例,它使用两个标记类型来显示调度发生的位置,并使用方法调用的链接。为方便起见,我提供了一个程序,否则您将不得不使用临时变量。我已经使用了Create_Object,但显式调用了" new",但这当然是同样的事情。另外,我已经展示了一个例子,当Ada静态地知道所涉及的类型时,它不会进行动态调度。这实际上是一个很好的功能(性能方面),即使它确实需要关注(甚至专家也时不时地被咬:=)
with Utils; use Utils;
procedure Chain is
O : access Object := new Object;
C : access Child := new Child;
begin
O.Add (1).Add (2);
C.Add (3).Add (4);
end Chain;
package Utils is
type Object is tagged null record;
function Add (Self : access Object; Val : Integer) return access Object;
procedure Add (Self : access Object; Val : Integer); -- for convenience
type Child is new Object with null record;
overriding function Add (Self : access Child; Val : Integer) return access Child;
overriding procedure Add (Self : access Child; Val : Integer); -- for convenience
end Utils;
with Ada.Text_IO; use Ada.Text_IO;
package body Utils is
function Add (Self : access Object; Val : Integer) return access Object is
begin
Put_Line ("func Object.Add" & Val'Img);
Self.Add (Val); -- static call, not dynamic dispatch
return Self;
end Add;
procedure Add (Self : access Object; Val : Integer) is
begin
Put_Line ("proc Object.add" & Val'Img);
end Add;
overriding function Add (Self : access Child; Val : Integer) return access Child is
begin
Put_Line ("Child.Add" & Val'Img);
Self.Add (Val); -- static call, not dynamic dispatch
return Self;
end Add;
overriding procedure Add (Self : access Child; Val : Integer) is
begin
Put_Line ("proc Child.Add" & Val'Img);
end Add;
end Utils;
该程序的输出是:
func Object.Add 1
proc Object.add 1
proc Object.add 2
Child.Add 3
proc Child.Add 3
proc Child.Add 4
编辑:正如评论中所讨论的,建议始终使用覆盖以确保该过程确实覆盖,而不是使用不同的配置文件。访问参数确实创建了一个原始操作。
答案 2 :(得分:0)
从第18段开始,函数[formal]参数只能使用'in'模式(只读)。因此输入对象不会被修改。
18 {参数模式}形式参数的参数模式用实际参数传递信息传递的方向:in,in out或out。 Mode in是默认值,是access_definition定义的参数模式。函数的形式参数(如果有的话)应具有模式。[Ada 2005]
所以我不认为该语言支持它,如其他语言所示。
但是,如果您不介意复制,我们可以将结果保存回对象中,但这与您引用的其他语言不同。
obj := obj.set("this").set(123).set(some_other_type);
您在'obj'的副本上设置“this”并返回该副本。从该副本中,我们创建一个新副本并在该副本中设置123,然后返回该副本。最后,复制了最后一个结果,并将'some_other_type'设置为它。返回最后一个副本,我们可以将其保存在obj中。请注意,如果set()
函数足够小并且内联,那么优化的实现可以避免大多数(如果不是全部)副本,但我不能使用它。
回想起来,使用程序:
obj.set("this");
obj.set(123);
obj.set(some_other_type);
根本不会复制。