【问题标题】:Access parent class instance variable访问父类实例变量
【发布时间】:2011-02-21 21:44:54
【问题描述】:

这如何工作?

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

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

【问题讨论】:

    标签: ruby instance-variables


    【解决方案1】:

    您希望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
    

    【讨论】:

      【解决方案2】:

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

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

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

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

      【讨论】:

      • 非常好的答案,除了一件事:更改子类构造函数的签名完全没问题。那是因为当你实例化一个类时,你总是知道你在处理什么类。因此,构造函数不需要考虑多态性。 (值得注意的例外:在进行元编程或创建某种魔法工厂时,您可能希望构造函数具有相同/相似的接口。)
      • 您对构造函数签名有点正确-它们没问题。改变。这并不意味着基类和子类构造函数的行为完全不同是很好的。
      【解决方案3】:

      John Nunemaker 在这个话题上有一个很好的article

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-21
        • 1970-01-01
        • 2022-08-11
        相关资源
        最近更新 更多