访问父类实例变量

5
这怎么能实现呢?
class A
  attr_accessor :name

  def initialize params
    @name = params[:name]
    @collection << B.new 
  end
end

class B < A
  def initialize
    @my_name = lookup_something(<parent.name>)
  end
end

基本上,我需要从父类中获取一个值,在子类上进行查找,但如果有更好的方法,我不想显式地传递它。父类的实例变量在子类中完全无法访问吗?还是这只是层次结构设计不良的表现?
3个回答

8
我不太清楚你在这里想要做什么- 你发布的所有代码都对实例变量起作用。实例变量是针对每个对象而不是每个类的,因此当你说“我需要从父类获取一个值”时,我不知道你的意思。
以下是关于你的代码需要注意的几点:
- 基类不应该知道子类的存在。因此,在A#initialize中创建B对象是不好的,因为基类使用了子类。 - 你正在用完全不同的行为覆盖类B#initialize与类A#initialize。子类的对象应该像其父类的对象一样表现。 - 在调用B.new('myname')时,@ name变量永远不会被分配,因为没有调用A#initialize方法。你必须要么调用super(:name => name)(以运行超类initialize),要么直接在B#initialize中对@ name进行赋值。 - 一旦定义了@ name,所有实例方法都可以使用它的值。包括在父/超类中定义的方法。
我不太确定为什么你在这里使用继承,我有种感觉这不是你想要的。如果你有两个用于两个不同内容的类,那就不应该涉及继承。如果你想重复使用代码,请查看Ruby的mixin功能,或将你的复杂对象组合成几个具有你想要重复使用的行为的“较小”对象。

非常好的回答,除了一件事:更改子类构造函数的签名完全没有问题。这是因为在实例化一个类时,您总是知道正在处理哪个类。因此,在构造函数中不需要考虑多态性。(值得注意的例外情况:当您进行元编程或创建某种魔法工厂时,可能希望构造函数具有相同/类似的接口。) - Franz
你对构造函数签名的看法有一定道理 - 它们可以更改。但这并不意味着基类和子类构造函数具有完全不同的行为是很好的。 - averell

3
约翰·纽曼克尔(John Nunemaker)在该主题上撰写了一篇很好的文章。 文章链接

2
你为什么希望BA继承?除非你有其他原因,否则设计这个的正确方法是只需将名称作为B构造函数的参数并放弃继承。
class A
  attr_accessor :name

  def initialize params
    @name = params[:name]
    @collection << B.new(@name)
  end
end

class B
  def initialize name
    @my_name = lookup_something(@name)
  end
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接