gpt4 book ai didi

ruby-on-rails - 在 Ruby 中初始化类实例变量

转载 作者:数据小太阳 更新时间:2023-10-29 06:31:28 25 4
gpt4 key购买 nike

我正在开发一个小型 Rails 应用程序,但遇到了 ruby​​ 的 OOP 模型问题。我有以下简化的类结构。

class Foo
protected
@bar = []
def self.add_bar(val)
@bar += val
end
def self.get_bar
@bar
end
end

class Baz < Foo
add_bar ["a", "b", "c"]
end

我现在的问题是,当我在 Baz 的类定义中调用 add_bar 时,@bar 显然没有初始化,我得到一个错误,提示 + 运算符是不适用于 nil。直接在 Foo 上调用 add_bar 不会产生这个问题。为什么会这样,我该如何正确初始化 @bar

为了明确我想要什么,我将指出我期望从这些类中获得的行为。

Foo.add_bar ["a", "b"]
Baz.add_bar ["1", "2"]
Foo.get_bar # => ["a", "b"]
Baz.get_bar # => ["a", "b", "1", "2"]

我怎样才能做到这一点?

最佳答案

简答:实例变量不会被子类继承

更长的答案:问题是您在类的主体中(在任何方法之外)编写了 @bar = []。当您设置实例变量时,它存储在当前 self 上。当您在类主体中时,self 是类对象 Foo。因此,在您的示例中,@foo 在类对象 Foo 上定义。

稍后,当您尝试查找实例变量时,Ruby 会查找当前是 self 的任何内容。当你从 Baz 调用 add_bar 时,self 就是 Baz。此外,self 在 add_bar 的主体中仍然是 Baz(即使该方法在 Foo 中)。所以,Ruby 在 Baz 中寻找 @bar 但找不到它(因为你在 Foo 中定义了它)。

这里有一个例子可以使这个更清楚

class Foo
@bar = "I'm defined on the class object Foo. self is #{self}"

def self.get_bar
puts "In the class method. self is #{self}"
@bar
end

def get_bar
puts "In the instance method. self is #{self} (can't see @bar!)"
@bar
end
end

>> Foo.get_bar
In the class method. self is Foo
=> "I'm defined on the class object Foo. self is Foo"

>> Foo.new.get_bar
In the instance method. self is #<Foo:0x1056eaea0> (can't see @bar!)
=> nil

诚然,这有点令人困惑,并且是 Ruby 新手的常见绊脚石,所以不要难过。当我阅读 Programming Ruby(又名“The Pickaxe”)中的“元编程”一章时,我终于明白了这个概念。

我如何解决您的问题:看看 Rails 的 class_attribute 方法。它允许您尝试做的事情(在父类上定义一个可以在其子类中继承(和覆盖)的属性)。

关于ruby-on-rails - 在 Ruby 中初始化类实例变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4901208/

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