2017-06-09 44 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' –