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

ruby中的子类可以访问实例变量吗?,ruby,Ruby,我最近开始学习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

我最近开始学习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
我知道实例变量只属于一个类,它的子类是独立的。但我的人类类是如何从动物类访问@sound的呢

我的人类课程是如何从动物课程中获取@声音的


没有。它访问了继承的方法(
Animal#Animal_sound
)。当您执行
human.animal\u sound
时,它会将
@sound
附加到当前的
self
,即
human
——实例(而不是
human
,也不是
animal
@sound
不属于类;它属于实例(这就是为什么它被称为实例变量)。然后,
human.human\u sound
再次从当前的
self
读取
@sound
,即
human
(不是从
human
,不是从
Animal
)继承
human
类。因此,
Animal
类中的实例变量
@sound
initiate可以在
Human
类中访问


与继承父类属性的子类类似。

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

下面是一个例子:

class Animal
  def animal_sound
    @sound = "roar"
    @sound + " "+"animal"
  end
  # This reader-method lets us see the value of the @eye_colour instance-variable
  def eye_colour
    "My eyes are: #{@eye_colour}"
  end
  # This writer-method lets us set the value of the @eye_colour instance variable 
  def eye_colour=(new_colour)
    @eye_colour = new_colour
  end
end
class Human < Animal
  def human_sound
    @sound + " "+"human"
  end
  # inherits the colour-methods from Animal
end

# when you create a new instance of human, you can give them an eye-colour
human = Human.new
human.eye_colour = "Green"
human.eye_colour # => "My eyes are: Green"

# if you create a new instance of human, you can give them a different eye colour
human2 = Human.new
human2.eye_colour = "Brown"
human2.eye_colour # => "My eyes are: Brown"

# but the first human is still the original colour - 
# because the variable contains a value just for *that* instance.
# This is what it means to be an instance-variable   
human.eye_colour # => "My eyes are: Green"
类动物
动物之声
@sound=“咆哮”
@声音+“”+“动物”
结束
#这个reader方法让我们看到@eye\u color实例变量的值
眼睛颜色
“我的眼睛是:{@eye\u color}”
结束
#这个writer方法允许我们设置@eye\u color实例变量的值
def眼睛颜色=(新颜色)
@眼睛颜色=新颜色
结束
结束
类人<动物
人声
@声音+“”+“人类”
结束
#继承了动物的色彩方法
结束
#当你创建一个新的人类实例时,你可以给他们一个眼睛颜色
人
人眼颜色=“绿色”
human.eye_color#=>“我的眼睛是绿色的”
#如果你创建了一个新的人类实例,你可以给他们一个不同的眼睛颜色
human2=Human.new
人眼2.眼睛颜色=“棕色”
人眼颜色“我的眼睛是棕色的”
#但是第一个人类仍然是原始的颜色-
#因为变量只包含*该*实例的值。
#这就是作为实例变量的含义
human.eye_color#=>“我的眼睛是绿色的”

Ruby实例由

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

                                             ...
                                              |
                                            Object { ... }
                                              |
                                            Animal { def animal_sound }
    human -----> {@sound}                     |
                  <type>  ----------------> Human { def human_sound }
    
    。。。
    |
    对象{…}
    |
    动物{def Animal_sound}
    人类------>{@sound}|
    ---------------->人类{def Human_sound}
    
    human
    实例上可用的任何实例方法(行为)都将对第1部分中的同一组实例变量进行操作。在您的示例中,这是
    {@sound}

    实例变量本身并不是“继承”的,但由于它们存在于实例本身的上下文中,所以实例拥有的任何和所有方法都可以访问它们

    将对象视为具有关联方法和实例变量的容器。您可以根据自己的需要添加、删除和更改这些方法,尽管通常在类定义中只添加和删除一次方法。因为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"
    
    类动物
    def初始化(名称=nil)
    #定义定义其名称的本地实例变量
    @name=name | |贝西'
    结束
    动物之声
    #动物发出的默认噪音
    “哞”
    结束
    def声音
    #更个性化的音效
    “%s转到%s”%[@name,动物音]
    结束
    结束
    类人<动物
    动物之声
    #重写基于名称的默认行为
    大小写(@name)
    当‘布鲁斯’
    #任何一个叫布鲁斯的人都会做一些不同的事情
    “哟”
    其他的
    “罗尔”
    结束
    结束
    结束
    chucky=人类。新(“chucky”)
    p.楚基声音
    #=>“Chucky变为rawr”
    bruce=人类。新建('bruce')
    布鲁斯·桑德
    #=>“布鲁斯去溜溜球”
    
    在这里,
    @name
    是在父类初始值设定项中分配的,但它绑定到实例本身,而实例本身实际上是
    Human
    类型,因此它可以通过Human中的
    animal\u sound
    等任何方法访问。请注意,这也是相反的,父类正在调用
    animal\u sound
    ,但最终使用的是子类版本,而不是父类版本,因为子类定义了不同的行为


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

    人类类实际上与:

    class Human
      def animal_sound
        @sound = "roar"
        @sound + " " + "animal"
      end
    
      def human_sound
        @sound + " " + "human"
      end
    end
    
    对于您的新实例
    human=human.new
    ,当您调用
    animal\u sound
    时,这将为您的特定实例
    human
    定义
    @sound

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

    请注意,如果在
    animal\u sound
    之前调用
    human\u sound
    @sound
    将返回
    nil
    ,这将导致错误。由于
    @sound
    将在其他地方使用,因此在特殊的
    initialize
    方法中定义它是合理的。这边
    @soundclass Human
      def animal_sound
        @sound = "roar"
        @sound + " " + "animal"
      end
    
      def human_sound
        @sound + " " + "human"
      end
    end
    
    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"