Comment mettre en œuvre une classe abstraite en ruby?
Je sais il n'y a pas de notion de classe abstraite en ruby. Mais si elle doit être mise en œuvre, comment aller à ce sujet? J'ai essayé quelque chose comme...
class A
def self.new
raise 'Doh! You are trying to write Java in Ruby!'
end
end
class B < A
...
...
end
Mais quand j'essaie d'instancier B, il est à l'intérieur va demander A.new
qui va faire l'exception.
Aussi, les modules ne peuvent pas être instanciées, mais ils ne peuvent pas être héritée trop. faire de la nouvelle méthode privée ne fonctionnera pas. Les pointeurs?
- Les Modules peuvent être mélangés, mais je suppose que vous devez classique héritage pour une autre raison?
- C'pas que j'ai besoin d'implémenter une classe abstraite. Je me demandais à propos de la façon de le faire, si, à tout ce qu'on doit faire. Un problème de programmation. Thats it.
raise "Doh! You are trying to write Java in Ruby"
.
Vous devez vous connecter pour publier un commentaire.
Je n'aime pas utiliser les classes abstraites en Ruby (il n'y a presque toujours une meilleure façon). Si vous pensez vraiment que c'est la meilleure technique pour la situation même si, vous pouvez utiliser le code suivant pour être plus déclaratif sur les méthodes sont abstraites:
Fondamentalement, il vous suffit d'appeler
abstract_methods
avec la liste des méthodes sont abstraites, et quand ils obtiennent appelé par une instance de la classe abstraite, unNotImplementedError
exception sera levée.NotImplementedError
ce qui signifie essentiellement "dépend de la plateforme, non disponible sur le vôtre". Voir les docs.Juste à carillon tard ici, je pense qu'il n'y a pas de raison d'arrêter quelqu'un à partir de l'instanciation de la classe abstraite, en particulier parce qu'ils peuvent ajouter des méthodes à la volée.
De canard-typage des langues, comme le Rubis, la présence/absence ou le comportement de méthodes lors de l'exécution afin de déterminer si elles devraient être appelée ou non. Donc à votre question, tel qu'il s'applique à un résumé méthode, sens
et qui devrait être sur la fin de l'histoire. La seule raison d'utiliser les classes abstraites en Java consiste à insister pour que certaines méthodes get "rempli", alors que d'autres ont de leur comportement dans la classe abstraite. Dans un canard en tapant la langue, l'accent est mis sur les méthodes, pas sur les classes/types, de sorte que vous devez déplacer vos soucis à ce niveau.
Dans votre question, vous êtes essentiellement en essayant de recréer la
abstract
mot clé de Java, qui est un code-odeur pour faire du Java en Ruby.Essayez ceci:
#initialize
de B, vous pouvez en fait juste souligner que ce soit dans Un#initialiserif self.class == A
.Mes 2 cents: j'opte pour une solution simple, léger DSL mixin:
Et, bien sûr, l'ajout d'une autre erreur pour l'initialisation de la classe de base serait négligeable dans ce cas.
err = NotImplementedError.new(message); err.set_backtrace caller()
YMMVpour n'importe qui dans les rails monde, la mise en œuvre d'un ActiveRecord modèle comme une classe abstraite est fait avec cette déclaration dans le fichier de modèle:
Dans les derniers 6 ans 1/2 de programmation Ruby, je n'ai pas nécessaire une classe abstraite une fois.
Si vous pensez vous avez besoin d'une classe abstraite, vous êtes trop réfléchir dans un langage qui fournit/nécessite, non pas en Ruby, en tant que tel.
Comme d'autres l'ont suggéré, un mixin est plus approprié pour les choses qui sont censé être des interfaces (comme Java définit), et de repenser votre modèle est plus approprié pour des choses que le "besoin" de classes abstraites à partir d'autres langages comme C++.
Mise à jour 2019: je n'ai pas besoin classes abstraites en Ruby dans 16½ des années d'utilisation. Tout ce que tous les gens commentant ma réponse dites est adressée par le fait de l'apprentissage de Ruby et en utilisant les outils appropriés, comme des modules (qui même vous donner communes des implémentations). Il y a des gens sur les équipes, j'ai réussi, qui ont créé des classes qui ont de la base de la mise en œuvre qui ne parviennent pas (comme une classe abstraite), mais ce sont principalement des déchets de codage car
NoMethodError
produirait exactement le même résultat qu'unAbstractClassError
dans la production.Vous pouvez essayer 3 rubygems:
interface
résumé
abstrait simple
Personnellement je relance NotImplementedError dans les méthodes de classes abstraites. Mais vous voudrez peut-être laisser sortir de la "nouvelle " méthode", pour les raisons que vous avez mentionnées.
initialize
méthodes n'est pas appelée automatiquement sauf s'il est explicitement appelé avec super.Si vous voulez aller avec une uninstantiable classe, dans votre A. nouvelle méthode, vérifier si auto == Un avant de les jeter à l'erreur.
Mais vraiment, un module semble plus proche de ce que vous voulez ici — par exemple, Énumérable est le genre de chose qui pourrait être une classe abstraite dans d'autres langues. Vous techniquement ne peut pas sous-classe, mais en l'appelant
include SomeModule
atteint à peu près le même objectif. Est-il quelque raison que cela ne fonctionne pas pour vous?Quel but êtes-vous essayer de servir avec une classe abstraite? Il y a sans doute une meilleure façon de le faire en ruby, mais vous n'avez pas donné de détails.
Mon pointeur est-ce; utiliser un mixin pas l'héritage.
Une autre réponse:
Cela repose sur le normal #method_missing à signaler, mis en oeuvre des méthodes,
mais garde les classes abstraites d'être mis en œuvre (même si ils ont une méthode initialize)
Comme les autres affiches ont dit, vous devriez probablement être l'aide d'un mixin si, plutôt que d'une classe abstraite.
J'ai fait de cette façon, il redéfinit de nouvelles sur les enfants de la classe de trouver un nouveau non classe abstraite.
Je ne vois pas de pratique dans l'utilisation de classes abstraites en ruby.
Il y a aussi cette petite
abstract_type
gem, permettant de déclarer les classes abstraites et les modules d'une façon discrète.Exemple (à partir de la README.md fichier):
Rien de mal avec votre approche. Générer une erreur dans initialiser semble bien, aussi longtemps que l'ensemble de vos sous-classes remplacer initialiser bien sûr. Mais vous ne voulez pas définir de soi.des nouvelles comme ça. Voici ce que je ferais.
Une autre approche serait de mettre tout ce que la fonctionnalité dans un module, qui comme vous l'avez mentionné ne peut jamais être instiated. Ensuite inclure ce module dans vos classes plutôt que d'en hériter d'une autre classe. Cependant, ce serait de casser des choses comme super.
Donc, cela dépend de la façon dont vous voulez de la structure. Bien que les modules sembler comme une solution de nettoyage pour résoudre le problème de "Comment puis-je écrire des trucs qui est destiné à d'autres classes à utiliser"
2 lignes de bijou : https://rubygems.org/gems/abstract