gpt4 book ai didi

raku - 在Raku中混合使用私有(private)属性和公共(public)属性以及访问器

转载 作者:行者123 更新时间:2023-12-03 14:34:27 24 4
gpt4 key购买 nike

#Private attribute example
class C {
has $!w; #private attribute
multi method w { $!w } #getter method
multi method w ( $_ ) { #setter method
warn “Don’t go changing my w!”; #some side action
$!w = $_
}
}
my $c = C.new
$c.w( 42 )
say $c.w #prints 42
$c.w: 43
say $c.w #prints 43

#but not
$c.w = 44
Cannot modify an immutable Int (43)

到目前为止,如此合理,然后
#Public attribute example
class C {
has $.v is rw #public attribute with automatic accessors
}
my $c = C.new
$c.v = 42
say $c.v #prints 42

#but not
$c.v( 43 ) #or $c.v: 43
Too many positionals passed; expected 1 argument but got 2

我喜欢‘=’赋值的即时性,但是我需要轻松捆绑多种方法提供的附带 Action 。我知道这是两个不同的世界,并且它们不会混合在一起。

但是-我不明白为什么我不能只去
$ c.v(43)
设置公共(public)属性
  • 我觉得raku指导我不要混合使用这两种模式-有些属性是私有(private)的,有些是公共(public)的,压力是方法方法(有些是冒号的糖)-这是Raku的设计意图吗?
  • 我错过了什么吗?
  • 最佳答案

    is this the intent of Raku's design?



    可以公平地说,Raku在这一领域并没有完全不受质疑。您的问题涉及Raku设计中的两个主题,这两个主题都值得讨论。

    Raku具有一流的l值

    Raku大量使用l值作为一流的东西。当我们写:
    has $.x is rw;

    生成的方法是:
    method x() is rw { $!x }

    此处的 is rw表示该方法返回的是左值-即可以分配给它的值。因此,当我们写:
    $obj.x = 42;

    这不是语法糖:它实际上是一个方法调用,然后将赋值运算符应用于它的结果。这是可行的,因为方法调用返回属性的 Scalar容器,然后可以将其分配给该容器。可以使用绑定(bind)将其分为两个步骤,以查看它不是一个简单的语法转换。例如,这:
    my $target := $obj.x;
    $target = 42;

    将分配给对象属性。相同的机制是许多其他功能(包括列表分配)的背后。例如,这:
    ($x, $y) = "foo", "bar";

    通过构造一个包含容器 List$x$y进行工作,然后在这种情况下,赋值运算符成对迭代每一边以进行赋值。这意味着我们可以在此处使用 rw对象访问器:
    ($obj.x, $obj.y) = "foo", "bar";

    这一切都自然而然地起作用了。这也是分配给数组切片和哈希的背后机制。

    也可以使用 Proxy 来创建一个l值容器,该容器的读写行为在您的控制之下。因此,您可以将副作用添加到 STORE中。然而...

    Raku鼓励使用语义方法而不是“setter”

    当我们描述OO时,经常会出现诸如“封装”和“数据隐藏”之类的术语。这里的关键思想是对象内部的状态模型可以自由发展,例如处理新需求,即对象内部的状态模型,即选择用来表示其实现其行为(方法)所需的数据的方式。对象越复杂,它就会变得越自由。

    但是,getter和setter方法是与状态具有隐式连接的方法。虽然我们可能会声称由于实现了数据隐藏,因为我们在调用方法而不是直接访问状态,但我的经验是,我们很快就处在外部代码正在执行setter调用序列以实现操作的地方-这是一种令人羡慕的特征反模式。而且,如果可以这样做,那么可以肯定的是,我们最终会在对象外部进行逻辑操作,该逻辑将执行getter和setter操作的混合操作以实现操作。实际上,这些操作应该已经公开为具有描述所要实现名称的名称的方法。如果我们处于并发设置中,这将变得更加重要。设计良好的对象通常很容易在方法边界进行保护。

    就是说, class的许多用途实际上是记录/产品类型:它们的存在是为了简单地将一堆数据项组合在一起。 .标记不仅会生成访问器,而且还会生成:
  • 使属性由默认的对象初始化逻辑设置(即class Point { has $.x; has $.y; }可以实例化为Point.new(x => 1, y => 2)),并在.raku转储方法中呈现该属性。
  • 将属性加入默认的.Capture对象,这意味着我们可以在解构中使用它(例如sub translated(Point (:$x, :$y)) { ... })。

  • 如果要以更具过程性或功能性的风格编写并使用 class作为定义记录类型的手段,则需要哪些东西。

    Raku设计并未针对在二传手中做聪明的事情而进行优化,因为这被认为是无法优化的。这超出了记录类型所需的范围;在某些语言中,我们可能会争辩说我们想对所分配的内容进行验证,但是在Raku中,我们可以为此使用 subset类型。同时,如果我们确实在进行OO设计,那么我们想要一个有意义的行为的API,该行为隐藏状态模型,而不是根据 setter/getter / setter/getter 进行思考,而这往往会导致代位失败。数据和行为,无论如何,这都是进行面向对象的重点。

    关于raku - 在Raku中混合使用私有(private)属性和公共(public)属性以及访问器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59671027/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com