【问题标题】:In Ruby, why is my base class only being puts once?在 Ruby 中,为什么我的基类只被放置一次?
【发布时间】:2013-06-03 15:12:33
【问题描述】:

我很高兴知道为什么下面的"Cat" 实例没有将"This animal can:" 文本放在其特定实例属性之前。我期待这样的输出:

This animal can:
Say it's name: 'Rover'
Bark
This animal can:
Say its name: 'Satan'
Meow

代码如下:

class Animal
    puts "This animal can:"
end

class Dog < Animal
    def initialize(name)
        @name = name
        puts "Say its @name: '%s'" % [name]
    end
    def bark
        puts "Bark"
    end
end

class Cat < Animal
    def initialize(name)
        @name = name
        puts "Say its @name: '%s'" % [name]
    end
    def meow
        puts "Meow"
    end
end

rover = Dog.new("Rover").bark
satan = Cat.new("Satan").meow

我看到的是这样的:

This animal can:
Say it's name: 'Rover'
Bark
Say its name: 'Satan'
Meow

"cat" 不是也继承自 Animal 类吗?它的输出不应该也以"This animal can:"开头吗?

【问题讨论】:

  • 理想情况下,两者都不会打印 puts "This animal can:"。这是你的完整代码吗?您使用哪个版本的 ruby​​?
  • 是的,这是我的完整代码(练习来自 Learn Ruby the Hard Way)。不幸的是,我只使用 Ruby 1.8.7(愚蠢的工作)。
  • 您的工作是否允许您安装到您的主目录?试用 RVM 来安装独立的 rubies。 rvm.io

标签: ruby class inheritance


【解决方案1】:

您的代码中的问题是:

puts "This animal can:"

在定义 Animal 类时运行。看来您希望在初始化程序中使用它:

class Animal
  def initialize(name)
    puts "This animal can:"
  end
end

然后,您需要在其他初始化程序中调用 super 以获得您期望的结果。

【讨论】:

  • 谢谢。好的,所以这个类只定义了一次。我感觉合理。但我正在创建它的两个新实例。那些新实例不继承基类的特征吗?
  • 它们继承了方法等。但是定义实际类的代码只运行一次(如解释/编译...)。
【解决方案2】:

“This Animal can:”行仅在定义类时出现,因为它不存在于方法中。由于这两种动物在它们的初始化程序中都有共同的行为,因此您可能希望将初始化程序提升到 Animal 类。

class Animal
  def introduce_myself
    puts "Hello! My name is #{@name} and I know how to: "
  end

  def initialize(name)
    @name = name
    introduce_myself
  end
end

class Dog < Animal
  def bark
    puts "Woof!"
  end
end

class Cat < Animal
  def meow
    puts "Meow!"
  end
end

Dog.new("Fido").bark
Cat.new("Sparky").meow

输出:

Hello! My name is Fido and I know how to: 
Woof!
Hello! My name is Sparky and I know how to: 
Meow!

【讨论】:

  • 谢谢。是的,推广初始化程序更有意义。 Ruby 的不要重复自己的哲学。好的,正在努力。
【解决方案3】:

您的 Animal 类没有定义构造函数,也没有被继承者调用:

class Animal
   def initialize
      puts "This animal can:"
   end
end

class Dog < Animal    
   def initialize(name)
       super()
       @name = name
       puts "Say its @name: '%s'" % [name]
   end

   def bark
       puts "Bark"
   end    
end

【讨论】:

  • 谢谢。 “构造函数”和方法/函数一样吗?
  • 来自Wikipedia:构造函数类似于实例方法,但它与方法的不同之处在于它没有显式返回类型,它不是隐式继承的,而且它通常对范围修饰符有不同的规则。您可以阅读更多关于构造函数的内容。
  • 我的意思是初始化器,是的,它被认为是 ruby​​ 中的常规方法(几乎)。
【解决方案4】:

没错!

class Animal
  def initialize(name)
    puts "This animal can:"
  end
end

def initialize(name)
  @name = name
  puts "Say its @name: '%s'" % [name]
  super # initializer from parent class
end

为什么不起作用?

class Animal
  puts "This animal can:"
end

当 ruby​​ 解析器读取代码时,它会评估所有内容。我的意思是即使你不创建任何对象,它也会显示“这个动物可以:”这就是为什么你第一次看到它并且觉得 Dog 类可以正常工作的原因

【讨论】:

    【解决方案5】:

    安装name_magic (gem install y_support) 玩得开心

    require 'y_support/name_magic';     
    
    class Animal
      include NameMagic
      def initialize; puts "This animal #{sound}s." end
      def sound; "growl" end
      def speak; puts "#{sound.capitalize}!" end
    end
    
    class Dog < Animal
      def sound; "bark" end
    end
    
    class Cat < Animal
      def sound; "meow" end
    end
    
    def hullo( animal )
      Animal.instance( animal ).speak
    end
    
    Rover = Dog.new
    #=> This animal barks.
    Satan = Cat.new
    #=> This animal meows.
    
    hullo :Rover
    #=> Bark!
    
    Animal.instances.each( &:speak )
    #=> Bark!
    #=> Meow!
    

    【讨论】:

    • 您知道nokogiri先生吗?如果是这样,那么我会问你一些问题。请确认您是否没有问题。 :)
    • 我知道nokogiri 作为 XML 解析器的存在。但是,我从未使用过它。我在工作中积极避免将 XML 作为一种数据格式,更喜欢 Ruby 内部 DSL。除此之外,我谈论任何事情都没有问题。
    猜你喜欢
    • 2011-04-02
    • 1970-01-01
    • 2011-12-31
    • 1970-01-01
    • 2019-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-20
    相关资源
    最近更新 更多