为什么你需要在ruby类中进行“初始化”?

时间:2013-11-22 03:21:07

标签: ruby initialization

我是红宝石的新手。

我没有得到的是,如果某些模式在我的代码中重复出现,我应该做些什么来减去那部分并保存问题。

,例如,现在看来是这样的:

class Book
  def initialize(title, author)
    @title = title
    @author = author
  end
  def info
    puts [@title, @author]
  end
end

我希望代码看起来像:

class Book(title, author)
  def info
    puts [title, author]
  end
end

我可以提出什么理由:

  1. 每次创建对象时都会调用initialize。所以,如果每次创建一个对象时我想做的事情,初始化是正式的方式。

  2. initialize表示构造函数将采用多少个参数。没有它,它将需要0。

  3. 但对我来说,它看起来仍然没用。有可能我可以改变语法看起来像第二个,而不是每次创建一个类时都要进行初始化,如果我没有什么特别的东西可以在构造时执行吗?

4 个答案:

答案 0 :(得分:4)

Struct确实存在:

Book = Struct.new(:title, :author)

book = Book.new('Fear & Trembling', 'Søren Kierkegaard')
book.title   #=> "Fear & Trembling"
book.author  #=> "Søren Kierkegaard"

您可以将新方法添加到Book中,而不是将其传递给块:

Book = Struct.new(:title, :author) do
  def info
    [title, author]
  end
end

book = Book.new('Zur Genealogie der Moral', 'Friedrich Nietzsche')
book.info  #=> ["Zur Genealogie der Moral", "Friedrich Nietzsche"]

或通过子类化:

class Book < Struct.new(:title, :author)
  def info
    [title, author]
  end
end

有关使用属性构建类的更多功能,请查看Virtus

答案 1 :(得分:2)

类不是方法,因此它不接受参数。初始化的目的是在新创建对象时执行任何类型的前期工作。例如:

book = Book.new('A Tale of Two Cities', 'Charles Dickens')
  #=> #<Book:0x007f9f5a8933d8 @title="A Tale of Two Cities", @author="Charles Dickens">

如果您向该类添加attr_accessor,您可以访问每个实例变量,如下所示:

class Book
  attr_accessor :title, :author
  def initialize(title, author)
    @title = title
    @author = author
  end
  def info
    puts [@title, @author]
  end
end  

book.title 
  #=> "A Tale of Two Cities" 
book.author
  #=> "Charles Dickens"

答案 2 :(得分:1)

免责声明:如果您只想要一个简单的属性包装(即没有花哨的方法),可以考虑使用类似OpenStruct或Hash的东西。

话虽如此,这里有一些元编程用于创建你所描述的简单类。

def simple_class *attrs
  klass = Class.new
  klass.class_eval do
    define_method('initialize') do |*args|
      if args.size != attrs.size
        raise ArgumentError.new("wrong number of arguments (#{args.size} for #{attrs.size})")
      end

      attrs.zip(args).each do |att, arg|
        instance_variable_set("@#{att}", arg)
      end
    end

    define_method('info') do
      attrs.map { |att| instance_variable_get("@#{att}") }
    end
  end

  klass
end

Book = simple_class(:title, :author)

b = Book.new("A BOOK", "ME")
puts b.info

答案 3 :(得分:0)

不,你不能改变固有的Ruby语言来做你所建议的。但是,由于语言非常灵活,您可以定义一种基本上与您描述的行为相似的方法,例如。

def new_class(class_name, *class_args)
  # insert Ruby metaprogramming code here
end

new_class(:Book, :title, :author) do
  def info
    puts [title, author]
    end
  end
end