gpt4 book ai didi

ruby - 如何创建不在子级之间共享状态的类变量

转载 作者:太空宇宙 更新时间:2023-11-03 16:40:37 24 4
gpt4 key购买 nike

我希望创建一种方法让子类在类级别表达一些业务定义。

我尝试为此使用类变量,但我发现它们在所有类之间共享状态,所以一旦我定义了第二个类,“@@attribute”类变量就会更改所有相邻类实例的值。

class Parent
def self.type(value)
@@_type = value
end

def render
puts @@_type
end
end

class Children < Parent
type "name"
end

Children.new.render # Result: name. Expected: name

class Children2 < Parent
type "title"
end

Children2.new.render # Result: title. Expected: title
Children.new.render # Result: title. Expected: name

如何以最简单直接的方式创建此 DSL?这是一些 Ruby Gem 的常见模式,例如 HTTParty、Virtus 等。

我什至试图查看他们的源代码以了解它是如何完成的,但对于我想要的东西来说它似乎太复杂了。

感谢您的帮助!

最佳答案

类变量是最有经验的 Rubiest 很少使用的 Ruby 工具中的一种。1。相反,您想使用类级实例变量Parent 是类Class 的实例。

class Parent
def self.type=(value)
@type = value
end

def self.type
@type
end

def render
puts self.class.type
end
end

class Children < Parent
self.type = "name"
end

Children.new.render
#=> "name"

class Children2 < Parent
self.type = "title"
end

Children2.new.render
#=> "title"
Children.new.render
#=> "name"

首先,类方法type=被称为“setter”,类方法“type”被称为“getter”。你有一个 setter type,接受一个参数。如果你这样做,你将如何获得它的值(value)?要将它也用作 setter/getter ,您必须执行以下操作:

  def self.type=(value=nil)
if value.nil?
@type
else
@type = value
end
end

在这里定义一个 getter 会更有意义

  def self.type
@type
end

并且没有 setter,只是编写,例如,@type = "name"

这很笨拙,只有在您不想将 @type 设置为 nil 时才有效。您也可以将您的方法保留为 setter 并使用 self.class.instance_variable_get(:@type) 来获取它的值,但这同样糟糕。最好有一个 setter 和一个 getter。

当使用 setter 时,我们需要在 type 前面加上 self. 以告诉 Ruby 我们希望调用 getter 而不是设置局部变量 type 给定值。当然,我们也可以只写,例如,`@type = "title"。

创建 setter 和 getter 的常规方法是编写 attr_accessor :type(调用类方法 Module#attr_accessor)。由于类方法存储在类的单例类中,因此可以按如下方式完成2:

class Parent
class << self
attr_accessor :type
end
def render
puts self.class.type
end
end

class Children < Parent
self.type = "name"
end

Children.new.render
#=> "name"

class Children2 < Parent
self.type = "title"
end

现在考虑实例方法Parent#render。作为实例方法,它的接收者是类(或子类)的实例,比如 parent = Parent.new。这意味着当在方法 self 中调用 render 时,等于 parent。然而,我们想要调用类方法 type。因此,我们必须将 parent 转换为 Parent,这是我们用 self.class 完成的。

1。另外两个(在我看来,当然)是全局变量和 for 循环。它们在 Ruby 新手中的受欢迎程度可能是因为它们往往在许多 Ruby 学习书籍的第一章中首次亮相。

2。在Parent 的单例类中定义attr_accessor 的方式有很多种。另外两个是 singleton_class.instance_eval do { attr_accessor :type }singleton_class.send(:attr_accessor, :type)

关于ruby - 如何创建不在子级之间共享状态的类变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56029489/

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