2017-06-09 5 views
0

instanziiert Wenn ich ein Book Modell haben:Wie man richtig eine Unterklasse in Ruby

class Book < ApplicationRecord 
    def calculate_page 
    . 
    . 
    end 
end 

Und ich erstellen Sie eine benutzerdefinierte Unterklasse ExtendedBook:

class ExtendedBook < Book 
end 

Wie ich ein erweitertes Buch Objekt do instanziiert, die erbt eine Buchinstanz mit ihren Instanzmethoden. Etwas auf den Linien von:

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

Damit ich schließlich in der Lage bin die @book ‚s Instanzmethoden direkt im @extended_book Objekt zu verwenden wie:

@extended_book.calculate_page 

, ohne manuell eine attr_getter definieren calculate_page in der Unterklasse .

+0

Wie sieht Ihre Methode 'Book # initialize' aus? Welche Instanzvariablen benutzt 'calculate_page' und wie sind sie mit' @ book' und '@ attributes_for_extended_book' verbunden? – spickermann

+0

Ich habe das Gefühl, was Sie jetzt haben sollten .... –

+1

Es ist nicht klar, was die Frage ist - in welchem ​​Kontext möchten Sie dies tun, und warum? Was ist ein 'ExtendedBook'? Sind es nur Methoden, die Sie zu "Book" hinzufügen möchten? Wie unterscheidet man ein "Book" von einem "ExtendedBook"? –

Antwort

1

Verwendung 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 

und stellen Sie sicher, eine attr_reader oder attr_accessor für jede Instanzvariable haben in Book Sie wollen delegieren.

2

Unterklassen erhalten automatisch die Methoden der Elternklasse.

Also, alles, was Sie brauchen würden, zu tun ist:

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

Jetzt könnten Sie Ihre Erweiterung wollen in der Lage sein, mit einem vorhandenen @book Objekt herum zu spielen. In diesem Fall wollen Sie keine Unterklasse, eher einen Dekorator.

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. 

Auf diese Weise kann Ihr ExtendedBook mit einem bereits instanziierten Book-Objekt interagieren.

Eine weitere Option ist die ExtendedBook Unterklasse Buch, zu erlauben, aber die erforderlichen Instanzvariablen in sich selbst zu kopieren. Vielleicht gefällt Ihnen dieser Ansatz besser.

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. 

Jeder hat Vor- und Nachteile, hängt davon ab, was Sie wollen.

+0

Ja, aber ich möchte vermeiden, '@total_pages = book.total_pages' zu setzen (wie in Ihrer letzten Lösung), da die' ExtendedBook' Klasse die 'Book'-Instanzmethoden stark verwenden und sie alle darin speichern muss Instanzvariablen fühlt sich an wie ein Overkill. Muss man das unvermeidlich machen? –

+0

Sie können das Buch einfach in '@ book' speichern und dann '@book.total_pages/2' innerhalb von' pages_in_half' verwenden, wenn total_pages öffentlich ist oder einen öffentlichen Getter hat –

Verwandte Themen