混淆实例方法从子类调用超类

时间:2013-03-02 17:12:55

标签: ruby

我只是在播放从子类中查看实例方法调用并使用我测试的以下代码:

class Animal
  def bark
    p "hukkhh"
  end
end
#=> nil

class Cow < Animal
end
#=> nil

Cow.public_instance_method(:bark)
#=> #<UnboundMethod: Cow(Animal)#bark>

class Cow
  bark
end
#=> NameError: undefined local variable or method `bark' for Cow:Class
#        from (irb):11:in `<class:Cow>'
#        from (irb):10
#        from C:/Ruby193/bin/irb:12:in `<main>'

从该代码我确认,如果没有相应类的对象实例,则无法执行实例方法。

但后来我尝试了以下代码:

def talk
  p "hi"
end
#=> nil

Object.public_instance_method(:talk)
#=> #<UnboundMethod: Object#talk>

class Foo
  talk
end
# prints: hi
#=> "hi"

这里的输出让我对我的第一个测试代码输出感到困惑。

有人能帮我理解上面这些事实吗?

1 个答案:

答案 0 :(得分:2)

您定义的方法talk属于Object,它是所有对象的根。所以talk方法可用于ruby中的所有对象。

def talk
  p "hi"
end

Object.respond_to? :talk  #=> true

现在,您定义了类Foo,它也是一个ruby对象。

Foo.is_a? Object  #=> true
Foo.respond_to? :talk  #=> ture

因此talk类可以使用Foo

现在,您使用方法Animal

定义一个类bark
class Animal
  def bark
    p "hukkhh"
  end
end
您定义的

bark方法属于Animal类,现在为instance level方法而非类级别。这意味着您需要创建类Animal的实例来调用bark

 Animal.respond_to? :bark  #=> false
 Object.respond_to? :bark  #=> false

 Animal.new.respond_to? :bark  #=> true
 Animal.respond_to? :talk   #=> true   #talk is available to Animal also because Animal is also object of Class
 Animal.new.respond_to? :talk  #=> true

现在您创建一个名为Cow的类,继承自Animal。因此bark可以使用Cow,除非它是overridden

 class Cow < Animal
 end

 Cow.respond_to? :bark  #=> false
 Cow.new.respond_to? :bark  #=> true
 Cow.respond_to? :talk  #=> true
 Cow.new.respond_to? :talk  #=> true

 Cow.new.bark #=> "hukkhh"  

因此,要调用bark,您需要创建类的实例。

如果要调用在子使用super

中重写的父方法
class Cow < Animal
  def bark
    super
    #do your stuff
  end
end

Cow.new.bark  #=> "hukkhh"