La représentation Ruby la plus proche d'une variable de classe 'private static final' et 'public static final' en Java?
Donné le code Java ci-dessous, ce qui est le plus proche que vous pourriez représenter ces deux static final
de variables dans une classe Ruby? Et, est-il possible en Ruby pour distinguer entre private static
et public static
variables qu'il est en Java?
public class DeviceController
{
...
private static final Device myPrivateDevice = Device.getDevice("mydevice");
public static final Device myPublicDevice = Device.getDevice("mydevice");
...
public static void main(String args[])
{
...
}
}
source d'informationauteur Hosh
Vous devez vous connecter pour publier un commentaire.
Il n'y a vraiment pas d'équivalent construire en Ruby.
Toutefois, il semble que vous faites un classique de portage des erreurs: vous avez un solution dans la langue et essayer de le traduire dans la langue B, quand ce que vous devriez vraiment faire est de trouver problème et ensuite de voir comment le résoudre dans la langue B.
Je ne peux pas vraiment être sûr de ce que le problème est que vous essayez de résoudre de petites codesnippet, mais ici, c'est un possible idée de comment le mettre en application en Ruby:
Voici un autre:
(La différence est que le premier exemple est paresseux, il ne s'initialise la variable d'instance lorsque l'attribut correspondant lecteur est appelée en premier. Le second initialise dès que le corps de la classe est exécutée, même si elles ne sont jamais nécessaires, tout comme la version de Java n'.)
Revenons sur quelques-uns des concepts ici.
En Ruby, comme dans tous les autres "bon" (pour diverses définitions de "bon") langage orienté objet, de l'état (variables d'instance, les champs, les propriétés, les fentes, les attributs, tout ce que vous voulez l'appeler) est toujours privé. Il est aucun moyen pour y accéder de l'extérieur. La seule façon de communiquer avec un objet en lui envoyant des messages.
[Note: à Chaque fois que j'écris quelque chose comme "no way", "toujours", "le seul moyen", etc., il ne signifie "pas question, sauf pour la réflexion". Dans ce cas particulier, il est
Object#instance_variable_set
par exemple.]En d'autres termes: en Ruby, les variables sont toujours privé, le seul moyen d'y accéder est par l'intermédiaire d'un getter et/ou de la méthode de définition, ou, comme ils sont appelés en Ruby, un attribut lecteur et/ou de l'écrivain.
Maintenant, je continue à écrire sur variables d'instancemais dans l'exemple Java, nous avons champs statiquesc'est à dire classe variables. Eh bien, en Ruby, contrairement à Java, les classes sont des objets, trop. Elles sont des instances de la
Class
classe et donc, comme tout autre objet, ils peuvent avoir des variables d'instance. Donc, en Ruby, l'équivalent d'une variable de classe est vraiment juste une norme variable d'instance qui appartient à un objet qui se trouve être une classe.(Il y a aussi la classe de la hiérarchie des variables, notée avec un double signe
@@sigil
. Ceux qui sont vraiment bizarre, et vous devriez probablement ignorer. La hiérarchie de classes de variables sont partagées à l'échelle de l'ensemble de la hiérarchie de classe, c'est à dire la classe à laquelle ils appartiennent, toutes ses sous-classes et de leurs sous-classes et de leurs sous-classes ... et aussi toutes les instances de toutes les classes. En fait, ils sont plus comme des variables globales que les variables de classe. Ils devraient vraiment être appelé$$var
au lieu de@@var
car ils sont beaucoup plus étroitement liée à des variables globales que les variables d'instance. Ils ne sont pas tout à fait inutiles, mais que très rarement utile).Donc, nous avons couvert le "champ" de la partie (Java champ == Ruby variable d'instance), nous avons couvert le "public" et "privé" des pièces (en Ruby, les variables d'instance sont toujours en privé, si vous voulez les rendre publics, l'utilisation d'un public de lecture/définition de la méthode) et nous avons couvert la partie "statique" (Java champ statique == Ruby variable d'instance de classe). Ce sujet de la "finale" de la partie?
En Java, la "finale" est juste une drôle de façon de l'orthographe "const", dont les concepteurs à éviter car la
const
mot-clé dans des langages comme le C et le C++ est subtilement cassé et qu'ils ne voulaient pas confondre les gens. Ruby ne ont des constantes (notée en commençant avec une majuscule). Malheureusement, ils ne sont pas vraiment constante, parce que d'essayer de les modifier, pendant la génération d'un avertissement, en fait, il fonctionne. Donc, ils sont plus d'une convention qu'un compilateur de l'exécution de la règle. Cependant, le plus important de la restriction des constantes c'est qu'ils sont toujours publiques.Ainsi, les constantes sont presque parfait: ils ne peuvent pas être modifiés (bien, ils ne devrait pas être modifié), c'est à dire qu'ils sont
final
ils appartiennent à une classe (ou un module), c'est à dire qu'ils sontstatic
. Mais ils sont toujourspublic
donc, malheureusement, ils ne peuvent pas être utilisées pour modéliserprivate static final
champs.Et c'est exactement le point où la pensée sur les problèmes au lieu de solutions. Qu'est-ce que vous voulez? Vous voulez de l'état qui
Vous pouvez obtenir tout cela, mais d'une manière complètement différente que dans Java:
||=
composé affectation pour affecter qu'une seule foisLa seule chose que vous avez à vous soucier, c'est que vous n'avez pas céder à
@my_public_device
n'importe où, ou, mieux encore, ne pas accéder à tous les. Toujours utiliser la méthode get.Oui, ce est un trou dans la mise en œuvre. Ruby est souvent appelé un "grown-up de la langue" ou un "adultes consentants de la langue", ce qui signifie qu'au lieu d'avoir le compilateur de mettre en place certaines choses, il vous suffit de les mettre dans la documentation et simplement faire confiance que vos collègues développeurs ont appris que le toucher d'autres personnes privées est impoli ...
Totalement différents approche à la vie privée est celle qui est utilisée dans les langages fonctionnels: l'utilisation de fermetures. Les fermetures sont des blocs de code sur leur environnement lexical, même après que l'environnement lexical a disparu hors de portée. Cette méthode de la mise en œuvre de privé de l'état est très populaire dans le Schéma, mais a récemment été popularisé par Douglas Crockford et coll. pour le JavaScript. Voici un exemple en Ruby:
Notez la subtile mais importante différence pour les versions au-dessus de ma réponse: l'absence de
@
sigil. Ici, nous créons local variables, pas instance variables. Dès que le corps de la classe se termine, ces variables locales tomber hors de portée et ne peut jamais être consulté à jamais. Seulement les deux blocs qui définissent les deux méthodes de lecture ont toujours accès à eux, parce qu'ils ferment sur le corps de la classe. Maintenant, ils sont vraiment privé et ils sontfinal
parce que la seule chose dans l'ensemble du programme qui a encore accès à eux est un pur getter méthode.Ce n'est probablement pas idiomatiques Ruby, mais pour n'importe qui avec un Lisp ou JavaScript, il devrait être assez clair. Il est aussi très élégant.
La chose la plus proche que je peux penser à une dernière variable est de mettre la variable en question comme une variable d'instance d'un module:
Ce sorties:
L'astuce ici est que par l'encapsulation de l'appareil dans un module, vous pouvez uniquement accéder à l'appareil par le biais de ce module. À partir de la classe
Foo
il n'y a pas moyen de modifier qui appareil auquel vous souhaitez accéder, sans agissant directement sur leDevice
de la classe ou de l'FinalDevice
module. Lefreeze
appel dansFinalDevice
peut ou peut ne pas être approprié, en fonction de vos besoins.Si vous voulez faire un public et privé de l'accesseur, vous pouvez modifier
Foo
comme ceci:Dans ce cas, vous devrez probablement modifier
FinalDevice::get_device
de prendre un argument.Mise à jour: @banister a souligné que
@fin
comme il l'a déclaré dansFinalDevice
est en effet accessible par une instance deFoo
. J'ai eu paresseusement suppose que puisqu'il n'était pas dans le texte par défaut de sortie parFoo#inspect
il n'était pas à l'intérieur deFoo
.Vous pouvez remédier à cela en plus explicitement
@fin
une variable d'instance de laFinalDevice
module:Qui génère correctement:
Et ouais,
require 'device'
si nécessaire.Bien que rien ne vous empêche de la redéfinition de la constante d'ailleurs, à l'exception d'un avertissement 🙂
private static en Ruby:
public static en Ruby:
Ruby pouvez pas avoir "final":)