在几个对象之间共享一个变量

时间:2013-10-21 00:50:10

标签: ruby

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的所有实例更改为@@dog_generic,它会起作用,但@@ variables很少使用,仅基于此,我不禁想到我会成为做错了。

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

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

4 个答案:

答案 0 :(得分: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

答案 1 :(得分:4)

你似乎对ruby中的全局变量有些困惑。你必须用$ sigil,la

明确地使它们成为全局的
$dog_generic = 'Woof'

def speak
    puts $dog_generic
end

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

答案 2 :(得分: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"

答案 3 :(得分:0)

虽然其他人回答了关于子类Dog的问题,但我想向您介绍一种更好的命名实例的方法:NameMagic。在命令行中输入gem install y_support,并在{:1>}下输入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]