1
class Collie
    def speak
        puts dog_generic
    end
end

class Greyhound
    def speak
        puts dog_generic
    end
end

class Labrador 
    def speak
        puts dog_generic
    end
end

dog_generic = "Woof" 

chep = Collie.new
wrex = Collie.new
speedy = Greyhound.new
faithful = Labrador.new

chep.speak #=> Woof
wrex.speak #=> Woof
speedy.speak #=> Woof
faithful.speak #=> Woof

我希望最后三种方法都返回“Woof”。但是,此代码将调用未定义变量 dog_generic错误。这似乎是因为即使是全局变量也对对象不可用。dog_generic如果我要更改to的所有实例@@dog_generic,它会起作用,但@@ variables很少使用,仅基于此,我不禁认为我做错了。

如何在多个对象之间共享一个变量?

不,我不想将一串“Woof”作为参数传递给每个对象。

4

4 回答 4

6

通常,人们会使用继承来提供这种行为:

class Dog
    def speak
        puts "Woof"
    end
end

class Collie < Dog
   # whatever behavior that is specific to Collie here
end

chep = Collie.new
chep.speak #=> Woof
于 2013-10-21T01:02:04.840 回答
4

您似乎对 ruby​​ 中的全局变量是什么感到有些困惑。您必须使用 $ sigil 明确地将它们设为全局,a la

$dog_generic = 'Woof'

def speak
    puts $dog_generic
end

也就是说,在这里使用全局变量可能是你最糟糕的方法。定义一个通用的狗类并让你的特定类型继承,或者创建一个狗混合并包含它都是恕我直言更好的解决方案。

于 2013-10-21T01:06:49.903 回答
1

做一个常数。任何以大写字母开头的变量都是常数。包括类,因此常量可以在全局范围内。 class Foo; end是一个指向一个类的常量,你也可以把它写成Foo = Class.new.

class Collie
  def speak
    puts DOG_GENERIC
  end
end

class Greyhound
  def speak
    puts DOG_GENERIC
  end
end

class Labrador 
  def speak
    puts DOG_GENERIC
  end
end

DOG_GENERIC = "Woof" 

chep = Collie.new
wrex = Collie.new
speedy = Greyhound.new
faithful = Labrador.new

chep.speak #=> Woof
wrex.speak #=> Woof
speedy.speak #=> Woof
faithful.speak #=> Woof

我同意@perimosocordiae,您可能应该使用继承。尽管在使用类进行继承方面,我不同意他的观点。Ruby 中的模块包含在继承链中,但是它们没有构造函数(您可以将它们视为抽象类,但您可以继承多个模块)。

module Speach
  WOOF = "Woof"
  QUACK = "Quack"

  module Dog
    def speak
      puts WOOF
    end
  end

  module Duck
    def speak
      puts QUACK
    end
  end
end

class Collie
  include Speach::Dog
end

class Greyhound
  include Speach::Dog

  # can overwrite ancestor
  def speak
    puts "Ruff"
  end
end

class Mallard
  include Speach::Duck
end

Collie.new.speak    # => "Woof"
Greyhound.new.speak # => "Ruff"
Mallard.new.speak   # => "Quack"
于 2013-10-21T02:07:33.073 回答
0

当其他人回答您关于子类化的问题Dog时,我想向您介绍一种更好的命名实例的方法:NameMagic. 输入gem install y_support您的命令行,并NameMagic通过以下方式要求它:

require 'y_support/name_magic'

接着:

class Dog
  include NameMagic
  def speak
    puts "Woof"
  end
end

Collie = Class.new Dog
Greyhound = Class.new Dog
Labrador = Class.new Dog

Chep = Collie.new
Wrex = Collie.new
Speedy = Greyhound.new
Faithful = Labrador.new

接着:

Dog.instances.each &:speak
#=> Woof
#=> Woof
#=> Woof
#=> Woof

NameMagic还允许您查询实例及其名称:

Dog.instances
#=> [#<Collie:0xb90e3c38>, #<Collie:0xb90e1adc>, #<Greyhound:0xb90e7860>, #<Labrador:0xb90e5574>]
Collie.instances
#=> [#<Collie:0xb90e3c38>, #<Collie:0xb90e1adc>]
Labrador.instances
#=> [#<Labrador:0xb90e5574>]
Dog.instance_names
#=> [:Chep, :Wrex, :Speedy, :Faithful]
Collie.instance_names
#=> [:Chep, :Wrex]
于 2013-10-21T03:23:00.797 回答