2017-06-09 43 views
0

如果我有一个Book模型:如何正确实例化一个子类中的红宝石

class Book < ApplicationRecord 
    def calculate_page 
    . 
    . 
    end 
end 

我创建一个自定义子类ExtendedBook

class ExtendedBook < Book 
end 

如何实例化一个继承扩展书对象一个书籍实例以及它的实例方法。东西上的线路:

@book = Book.first 
@extended_book = ExtendedBook.new (@book, @attributes_for_extended_book) 

所以,我最终能够直接使用@book的实例方法在@extended_book对象,如:

@extended_book.calculate_page 

,而无需手动定义attr_getter为ExtendedBook子类中的calculate_page

+0

你的'Book#initialize'方法是怎样的? 'calculate_page'使用哪些实例变量,以及它们如何连接到'@ book'和'@ attributes_for_extended_book'? – spickermann

+0

我觉得你现在应该工作...... –

+1

目前还不清楚问题是什么 - 在什么情况下你想这样做,为什么?什么是“ExtendedBook”?它只是你想添加到'Book'中的方法吗?你如何区分'Book'和'ExtendedBook'? –

回答

1

使用Forwardable

require 'forwardable' 

class ExtendedBook 
    extend Forwardable 

    attr_accessor :book 

    def_delegators :@book ,:total_pages,:my_other_method:,whatever 

    def initialize(book) 
    @book = book 
    end 

end 

,并确保有一个attr_readerattr_accessorBook要委托给每一个实例变量。

2

子类自动获取父类的方法。

因此,所有你需要做的是:

@extended_book = ExtendedBook.new 
@extended_book.calculate_page # This will work. 

现在,你可能希望你的扩展才能够玩与现有@book对象。在这种情况下,你不需要一个子类本身,更可能是一个装饰器。

class Book 
    def initialize(total_pages) 
    @total_pages = total_pages 
    end 
end 

class ExtendedBook 
    def initialize(book) 
    @book = book 
    end 

    def pages_in_half 
    return @book.total_pages/2 
    end 
end 

book = Book.new(10) 
ExtendedBook.new(book).pages_in_half # Returns 5. 

这样,您的ExtendedBook可以与已经实例化的Book对象进行交互。

另一种选择是允许ExtendedBook继承Book的子类,但将必要的实例变量复制到自身中。你可能更喜欢这种方法。

class ExtendedBook < Book 
    def initialize(book) 
    @total_pages = book.total_pages 
    end 

    def pages_in_half 
    return @total_pages/2 
    end 
end 

book = Book.new(10) 
ExtendedBook.new(book).pages_in_half # Returns 5. 

每个人都有优点和缺点,所以取决于你想要什么。

+0

是的,但我想避免必须设置'@total_pages = book.total_pages'(就像在你的后一种解决方案中一样),因为'ExtendedBook'类将大量使用Book的实例方法并且必须将它们全部存储实例变量感觉像是过度杀伤。那么必须这样做是不可避免的? –

+0

如果total_pages是公开的或者有一个公共getter,您可以将这本书保存在'@ book'中,然后在'pages_in_half'中使用'@book.total_pages/2' –