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

基本上,我需要父类中的一个值用于查找子类,但如果有更好的方法,我不想显式传递它。父类的实例变量在子类中是否完全不可访问?或者这只是糟糕的层次结构设计?

4

3 回答 3

8

我真的不知道您在这里要做什么-您发布的所有代码都适用于实例变量。实例变量是每个对象,而不是每个类,所以当你说“我需要来自父类的值”时,我不知道你的意思。

我在您的代码中注意到了几件事:

  • 基类永远不应该知道子类。所以在里面创建B对象A#initialize并不是一件好事,因为基类使用了子类。
  • 您正在B#initialize使用与A#initialize. 您甚至可以更改参数列表。也不是什么好事。子类的对象应该与其超类的对象具有相同的行为方式。
  • 当你调用B.new('myname')变量时@name永远不会被赋值,因为A#initialize方法永远不会被调用。您将不得不调用super(:name => name)(运行超类initialize)或者您必须@name直接分配给B#initialize
  • 一旦@name被定义,你所有的实例方法都可以使用它的值。包括在父/超类中定义的那些。

让我说我不太清楚你为什么在这里使用继承,我觉得这不是你想要的。如果您有两个用于两种不同事物的类,则永远不应该涉及继承。如果你想重用代码,要么看看 Ruby 的 mixin 特性,要么将你的复杂对象组合成几个具有你想要重用行为的“较小”对象。

于 2010-05-20T15:30:45.937 回答
3

John Nunemaker 有一篇关于这个主题的好文章。

于 2010-05-21T22:09:49.860 回答
2

你想B继承的原因是什么A?除非您有其他原因,否则设计它的正确方法是简单地将名称作为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
于 2010-05-20T14:41:51.560 回答