可以通过ruby中的子类访问实例变量吗?

时间:2016-10-06 03:46:23

标签: ruby

我最近开始学习红宝石。我想知道ruby中究竟是什么实例变量。我写了一个小代码来了解实例变量是什么。

class Animal
    def animal_sound
        @sound = "roar"
        @sound + " "+"animal"
    end
end
class Human < Animal
    def human_sound
        @sound + " "+"human"
    end
end
human = Human.new
p human.animal_sound
p human.human_sound

输出:

"roar animal"
"roar human"

我知道实例变量只属于一个类,它的子类是分开的。但是我的人类是如何从动物类中访问@sound的呢?

7 个答案:

答案 0 :(得分:3)

  

我的人类是如何从动物类中获取@sound的?

它没有。它访问了继承的方法Animal#animal_sound)。完成human.animal_sound后,它会将@sound附加到当前self,即human - 实例(不是Human,而不是Animal }})。 @sound不属于班级;它属于实例(这就是它被称为实例变量的原因)。然后,human.human_sound再次从当前@sound读取self,即human(不是来自Human,而不是来自Animal)。

答案 1 :(得分:2)

Ruby实例由

组成
  1. 实例变量(数据)的集合
  2. 对定义行为的类型的引用
  3. 在您的示例中,实例human可以解释为

                                             ...
                                              |
                                            Object { ... }
                                              |
                                            Animal { def animal_sound }
    human -----> {@sound}                     |
                  <type>  ----------------> Human { def human_sound }
    

    human实例上可用的任何实例方法(行为)都将在第1部分中的同一组实例变量上运行。在您的示例中,这是{@sound}

答案 2 :(得分:2)

实例变量不是&#34;&#34;继承&#34;本身,但由于它们存在于实例本身的上下文中,因此可以通过实例具有的任何和所有方法来访问它们。

将对象视为具有关联方法和实例变量的容器。您可以根据需要添加,删除和更改这些,但通常只在类定义中添加和删除方法一次。只是因为Ruby高度动态,你可以随时随地做到这一点。

例如,这是一个重写的演示:

class Animal
  def initialize(name = nil)
    # Define a local instance variable that defines their name
    @name = name || 'Betsy'
  end

  def animal_sound
    # Default noise an animal makes
    'moo'
  end

  def sound
    # A more personalized sound effect
    '%s goes %s' % [ @name, animal_sound ]
  end
end

class Human < Animal
  def animal_sound
    # Override the default behaviour based on name
    case (@name)
    when 'Bruce'
      # Where anyone named Bruce does something different
      'yo'
    else
      'rawr'
    end
  end
end

chucky = Human.new('Chucky')

p chucky.sound
# => "Chucky goes rawr"

bruce = Human.new('Bruce')

p bruce.sound
# => "Bruce goes yo"

此处@name在父类初始化程序中分配,但它绑定到实例本身,实际上是Human类型,因此任何方法都可以访问它比如人类中的animal_sound。请注意,这也是相反的,父类正在调用animal_sound,但最终使用的是子类版本,而不是父类,因为子类定义了不同的行为。

这是面向对象编程的基石。

答案 3 :(得分:1)

您的示例代码没有很好地使用实例变量...它显示了实例方法的使用(以及从父类继承它们)。实例变量是只能访问该实例的变量。

以下是一个例子:

/home/mona/devstack/

答案 4 :(得分:0)

Human类继承自Animal类。因此,在@sound类中启动的实例变量Animal可以在Human类中访问。

与继承父类属性的子类一样。

答案 5 :(得分:0)

人类实际上与以下相同:

class Human
  def animal_sound
    @sound = "roar"
    @sound + " " + "animal"
  end

  def human_sound
    @sound + " " + "human"
  end
end

对于新实例human = Human.new,当您致电animal_sound时,会为您的特定实例@sound定义human

因为@sound是一个实例变量,所以human可用的所有其他方法都可以使用它。也就是说,@sound也可以在human_sound中看到。

请注意,如果您在human_sound之前致电animal_sound@sound将返回nil,这将导致错误。由于@sound将在其他地方使用,因此在特殊的initialize方法中定义它是合理的。这种方式@sound自动定义为为每个新实例指定的。 现在,您调用animal_soundhuman_sound的顺序无关紧要。

class Human
  def initialize
    @sound = "roar" 
  end

  def animal_sound
    @sound + " " + "animal"
  end

  def human_sound
    @sound + " " + "human"
  end      
end

human = Human.new
human.human_sound  #=> "roar human"
human.animal_sound #=> "roar animal"

答案 6 :(得分:0)

  

我知道实例变量只属于一个类

没有。实例变量属于对象(也称为实例)。这就是为什么他们被称为实例变量的原因。

  

但我的人类是如何从动物类中获取@sound的呢?

不是。实例变量属于human