2010-05-20 178 views
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 

基本上,我需要一个值从父类的子类中查找使用,但我不想明确地传递,如果有一个更好的办法。父类的实例var在子类中完全无法访问?或者这仅仅是糟糕的层次结构设计?

回答

8

我真的不知道你正在尝试做的 - 所有的代码,你发布的作品上实例变量。实例变量是每个对象,而不是每个类,所以当你说“我需要父类的值”时,我不知道你的意思。

有几件事情,我注意到你的代码:

  • 基类应该永远意识到子类。因此在A#initialize中创建B对象不是一件好事,因为基础使用子类。
  • 您将以与A#initialize完全不同的行为覆盖类B#initialize你甚至改变参数列表。不是一件好事。子类的对象的行为方式应与其超类的对象相同。
  • 当您拨打B.new('myname')时,永远不会分配变量@name,因为永远不会调用A#initialize方法。你将不得不要么调用super(:name => name)(运行超initialize),或已分配给@name直接B#initialize
  • 一旦@name定义,所有的实例方法可以使用它的值。包括在父/超类中定义的那些。

让我说我不太清楚为什么你在这里使用继承,我觉得这不是你想要的。如果你有两个两个班不同东西,应该有从来没有被涉及的继承。如果您想重新使用代码,请查看Ruby的mixin功能,或者编写具有您想要重用的行为的几个“较小”对象的复杂对象。

+0

很好的答案,除了一件事:改变子类的构造函数的签名是完全正确的。这是因为当你实例化时,你总是知道你正在处理的是什么课。因此,构造函数不需要考虑多元模型。 (显着的例外:您可能希望对构造,当你在做的元编程,或者你建立某种神奇的工厂相同/相似的界面。) – Franz 2016-08-03 09:45:51

+0

你是一种权利有关的构造特征 - 它们是O.K.改变。这并不意味着拥有完全不同的基类和子类构造函数_behaviour_是很好的。 – averell 2016-08-23 09:53:24

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 
2

约翰Nunemaker关于这个话题有一个不错的article