2010-07-02 6 views
2

J'ai deux classes, Task et Subtask. La sous-tâche varie très peu de la tâche sauf pour une chose importante, elle doit inclure un module différent.Sous-classes Ruby: incluant différents modules basés sur l'héritage

Les modules inclus, subtask_module et task_module, ont tous les deux les mêmes méthodes et alias à mes fins, mais en interne, ils fonctionnent un peu différemment une fois que le module inclus étend ses méthodes. Il n'y a aucun moyen de contourner cela pour moi parce que j'utilise un plugin.

Par exemple, ci-dessous, vous voyez belongs_to dans tâche. belongs_to est étendu à partir du module inclus, mais sa fonction diffère légèrement en fonction du module que j'inclus.

class Subtask < Task 
    include subtask_module 
end 

class Task 
    include task_module 

    # methods and aliases both classes use (defined in included file) 
    # but behavior changes based on 
    # included file 
    belongs_to :template  
end 

Quelle est la meilleure façon de faire quelque chose comme ça? En ce moment, cela fonctionne comme maintenant. Mais il semble gonflé parce qu'il y aura des choses inutilisées déclarées dans la tâche dont je n'ai pas besoin.

Quel est le meilleur moyen?

+0

Pouvez-vous clarifier un peu la question? Parce que 'Subtask' étend' Task' vous pouvez appeler toutes les méthodes que vous pouvez appeler sur une 'Task' sur une' Subtask' (qu'elles soient définies explicitement dans 'Task' ou' included') et ensuite 'Subtask' peut ajouter son propres méthodes spécifiques qui ne sont pas disponibles sur 'Tasks'. Où sont les choses inutilisées déclarées dans 'Task'? – mikej

+0

Terminé. J'espère avoir éclairci les choses un peu. Je ne voudrais pas les séparer dans des fichiers séparés. J'ai aussi essayé d'utiliser un troisième AbstractModule en tant que Mixin mais j'avais aussi des problèmes avec ça. – Dex

+0

"D'où viennent les choses inutilisées déclarées dans la tâche?" - La réponse à cela n'est toujours pas claire pour moi. –

Répondre

4

Vous pouvez soit tourner la tâche dans une sous-classe aussi, alors avez chacun hériter de quelque chose de commun (en utilisant vos noms de dessus chaque fois que possible)

class Task 
    belongs_to :template  
end 

class Subtask1 < Task 
    include subtask_file 
end 

# this used to be Task, now is Subtask2 
class Subtask2 < Task 
    include task_file 
end 

Ou, vous déplacez la fonctionnalité partagée sur son propre module, puis incluez cela, et évitez complètement la superclasse/sous-classe (j'opterais pour celui-ci).

module TaskShared 
    belongs_to :template  
end 

class Task 
    include TaskShared 
    include task_file 
end 

class Subtask 
    include TaskShared 
    include subtask_file 
end 

(Le belongs_to peut vous donner des difficultés Si oui, essayez de l'ajouter dans le crochet inclus.)

module TaskShared 
    def self.included(klass) 
    klass.belongs_to :template 
    end 
end 

Notez qu'il ya des circonstances où cela devient collante, comme héritant de ActiveRecord: : Classes de base

+0

J'ai aussi essayé la dernière méthode. En fait, je voudrais hériter de ActiveRecord :: Base, MongoMapper, Mongoid, etc, j'essayais juste de garder la question aussi spécifique que non-bibliothèque. En effet, j'obtiens des erreurs avec les alias tels que belongs_to et validate. – Dex

+0

Je pense que j'aurais besoin de plus d'informations pour vous aider. Il y a longtemps que j'ai essayé de sous-classer une classe AR :: B, parce que ça a fini par être une énorme bogue de hacky. Si je me souviens, le plus gros problème est que la plupart de la magie repose sur diverses méthodes de réflexion qui changent lorsque vous sous-classe. Je l'ai contourné en passant outre un tas de méthodes pour mentir à AR. Sans connaître votre implémentation spécifique, je ne peux pas donner de conseil, mais en général, je pense que je dupliquerais le schéma, puis je déplacerais la fonctionnalité partagée vers un module et je l'inclurais. (ie j'implémente des énumérations de cette façon) –

+0

Je suis d'accord, ça va être une énorme douleur et je vais le diviser en deux fichiers. – Dex

Questions connexes