试图了解类和数组问题的一些东西

时间:2014-11-13 20:41:56

标签: ruby

Ruby新手在这里。以下代码不起作用。

class Shows 
    def echo
        x, y, z = self
        puts x
        puts y
        puts z
    end
end

["Foo", 2, 2001].echo

这样做。

class Array 
    def echo
        x, y, z = self
        puts x
        puts y
        puts z
    end
end

["Foo", 2, 2001].echo

我的理解是我可以通过

使Show成为Arrays的继承
class Shows < Arrays

但这也不起作用。

我知道我可以创建一个方法并像这样使用它

def echo(x, y, c)

    puts x
    puts y
    puts z
 end

然而,我想在第一段代码中这样做是有原因的。

3 个答案:

答案 0 :(得分:2)

在第一段代码中,当#echo上未定义echo时,您构建了一个数组,然后尝试在其上调用Array。您更接近于将Array子类化的想法,但您仍需要实例化Shows实例,而不是Array实例!

你可以这样做:

# Create a new class called Shows, which is a subclass of Array
class Shows < Array
  def echo
    # In this case, since self is an Array subclass structure, you can use
    # destructuring assignment to assign to x, y, and z
    x, y, z = self
    puts x
    puts y
    puts z
  end
end

# Create a new Shows instance, passing in an array of values that should populate it.
# This works because Shows#initialize inherits from Array#initialize, which accepts an
# array as an input value.
Shows.new(["Foo", 2, 2001]).echo

答案 1 :(得分:0)

第一位代码无法工作的原因是["Foo", 2, 2001]的类是一个数组。如果你编写一些代码来初始化一个show对象,那么你可以使用它的唯一方法就是它。例如,您可以执行以下操作:

s = Show.new("Foo", 2, 2001)
s.echo

要做到这一点,需要这样的事情:

class Show

  def initialize(name, day, year)
    @name = name
    @day = day
    @year = year
  end

  def echo
    puts @name
    puts @day
    puts @year
  end
end

这很有效,因为现在您将创建一个新的show对象,然后在该对象上调用show。另外,作为一种最佳实践,我通常会建议您不要在ruby中编辑Array类(或字符串,int ...),因为它会让事情变得混乱。

答案 2 :(得分:0)

Ruby中继承的好处是,层次结构中较低的类(或“子类”)可以访问(或“继承”)更高级别的类的功能。子类还可以添加自己的特定功能。

请考虑以下代码:

class Shows 
    def echo
        x, y, z = self
        puts x
        puts y
        puts z
    end
end

["Foo", 2, 2001].echo # => NoMethodError: undefined method `echo' for ["Foo", 2, 2001]:Array

[]语法是一个数组文字。它相当于Array.new。因此,这个:

["Foo", 2, 2001]       # => ["Foo", 2, 2001]

["Foo", 2, 2001].class # => Array

可能会像这样写得更乏味:

a = Array.new    # => []
a << "Foo"       # => ["Foo"]
a << 2           # => ["Foo", 2]
a << 2001        # => ["Foo", 2, 2001]

a.class          # => Array

我只向您展示这个较长的版本,以便更容易看到这一点:

["Foo", 2, 2001].echo

正在将echo邮件发送到班级Array的对象,但echo仅在班级Shows中定义。

同样,以下代码也遇到同样的问题:

class Shows < Array
    def echo
        x, y, z = self
        puts x
        puts y
        puts z
    end
end

["Foo", 2, 2001].echo # => NoMethodError: undefined method `echo' for ["Foo", 2, 2001]:Array

虽然班级Shows现在继承了班级Array的所有功能,但我们绝不会将echo讯息发送到班级Shows的对象 - 我们将消息发送到类Array的对象。

因此,只有您下面的示例才会按您期望的方式运行:

class Array 
    def echo
        x, y, z = self
        puts x
        puts y
        puts z
    end
end

["Foo", 2, 2001].echo # => Foo
                      # => 2
                      # => 2001

在某些情况下,继承类似Array的核心Ruby类并不一定是错误的决定。你应该在了解后果的情况下做到这一点。看看这篇文章:Beware subclassing Ruby core classes, by Steve Klabnik