gpt4 book ai didi

Ruby 内存和空对象模式

转载 作者:数据小太阳 更新时间:2023-10-29 07:54:49 26 4
gpt4 key购买 nike

你好 Rubyist,

想知道是否可以使用 Ruby 的内存运算符 ||=(即:a || a = b 编写 a ||= b) 可以用于应该遵循 null object patern 的自定义普通旧 ruby​​ 类.

例如,假设我有一个类:

class NoThing
def status
:cancelled
end

def expires_on
0.days.from_now
end

def gateway
""
end
end

我在没有 Thing 类的情况下使用它。 Thing 在其公共(public)接口(interface)中具有相同的statusexpires_ongateway 方法。

问题是,在 @thingnil 的情况下,我如何编写类似 @thing ||= Thing.new > 或 NoThing

最佳答案

可能FalseClass并在 NoThing 上设置相同的运算符方法。但出于多种原因,我会犹豫是否这样做。

与其他一些语言不同,Ruby 非常清楚有一组非常有限的东西是 false、falsenil。弄乱它可能会导致困惑和错误,它可能不值得你正在寻找的便利。

此外,Null Object Pattern 是关于返回一个对象,该对象与一个执行某些操作但什么都不执行的对象具有相同的接口(interface)。让它看起来像 false 会打败它。编写 @thing ||= Thing.new 的愿望与对空对象的愿望发生冲突。您总是希望设置 @thing,即使 Thing.new 返回 NoThing,这就是空对象的用途。使用该类的代码并不关心它使用的是 Thing 还是 NoThing

相反,对于那些你想区分 ThingNoThing 的情况,我建议使用很少的方法,例如 #nothing?。然后设置 Thing#nothing? 返回 falseNoThing#nothing? 返回 true。这允许您通过询问而不是通过硬编码类名来穿透封装来区分它们。

class NoThing
def status
:cancelled
end

def expires_on
0.days.from_now
end

def gateway
""
end

def nothing?
true
end
end

class Thing
attr_accessor :status, :expires_on, :gateway
def initialize(args={})
@status = args[:status]
@expires_on = args[:expires_on]
@gateway = args[:gateway]
end

def nothing?
false
end
end

此外,Thing.new 返回除 Thing 以外的任何内容都是不好的形式。这给应该是简单构造函数的东西增加了额外的复杂性。它甚至不应该返回 nil,它应该抛出异常。

相反,使用 Factory Pattern保持 ThingNoThing 纯粹和简单。将决定是否返回 ThingNoThing 的工作放在 ThingBuilderThingFactory 中。然后调用 ThingFactory.new_thing 来获取 ThingNoThing

class ThingFactory
def self.new_thing(arg)
# Just something arbitrary for example
if arg > 5
return Thing.new(
status: :allgood,
expires_on: Time.now + 12345,
gateway: :somewhere
)
else
return NoThing.new
end
end
end

puts ThingFactory.new_thing(4).nothing? # true
puts ThingFactory.new_thing(6).nothing? # false

然后,如果你真的需要它,工厂也可以有一个单独的类方法返回nil而不是NoThing允许@thing ||= ThingFactory.new_thing_or_nil。但是你不应该需要它,因为这就是空对象模式的用途。如果您确实需要它,请使用 #nothing? 和三元运算符。

thing = ThingFactory.new_thing(args)
@thing = thing.nothing? ? some_default : thing

关于Ruby 内存和空对象模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50535106/

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