2013-11-22 4 views
2

Я новичок в рубине.Зачем вам нужно «инициализировать» в классе ruby?

То, что я не получаю, если некоторые шаблоны повторяются в моем коде, должно быть что-то, что я мог бы сделать, чтобы вычесть эту часть и сохранить ее.

Например, вот что это выглядит сейчас:

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. Инициализация указывает, сколько аргументов примет конструктор. без которых потребуется 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 = 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 

Для e больше функциональности в создании классов с атрибутами, посмотрите на Virtus.

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" 
+0

Возможно ли, что я могу изменить синтаксис, чтобы он выглядел как второй, вместо того, чтобы выполнять инициализацию каждый раз, когда я создаю класс, если у меня нет ничего особенного для выполнения при построении? – Luxiyalu

+0

Со структурой, да: 'Book = Struct.new (: title,: author) do; def info; ставит "# {title}"; конец; end' – Zabba

+0

Тогда почему я не вижу, чтобы люди использовали его таким образом? Это просто обычаи или есть какие-то другие особенности об оригинальном классе? – Luxiyalu

0

Нет, вы не можете изменить присущий Рубиновый языку делайте то, что вы предлагаете. Однако, поскольку язык настолько гибкий, вы можете указать способ, который ведет себя по существу так, как вы описываете.

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 
+0

Итак, я ** мог ** определить новый класс, как указано выше (я предполагаю, что он ведет себя точно так же, как класс?). Но почему я не вижу, чтобы люди использовали его таким образом? – Luxiyalu

+0

Нет, 'new_class' будет методом, а не классом. Однако, если вы вызвали 'new_class', как я показал, то в результате выполнения этого метода класс' Book' будет определен по вашему запросу. То есть 'Book' будет определяться методом' initialization', в качестве параметров должны быть указаны 'title' и' author'. Что касается того, почему люди этого не делают, я думаю, что это потому, что они предпочитают язык так, как есть, и/или хотят использовать идиоматический подход. –

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 
Смежные вопросы