J’ai un programme qui ressemble à:
$offset = Point.new(100, 200); def draw(point) pointNew = $offset + point; drawAbsolute(point) end draw(Point.new(3, 4));
l’utilisation de $offset
semble un peu bizarre.
En C, si je définis quelque chose en dehors d’une fonction, c’est une variable globale automatiquement. Pourquoi Ruby doit-il être $offset
mais ne peut pas être offset
et être toujours global? Si c’est offset
, alors c’est un local? Mais local où, car il se sent très global.
Existe-t-il de meilleurs moyens pour écrire le code ci-dessus? L’utilisation de $offset
peut sembler un peu moche au début.
Mise à jour: je peux mettre ce décalage dans une définition de class
, mais que se passe-t-il si deux ou plusieurs classes doivent utiliser cette constante? Dans ce cas, dois-je encore définir un $offset
?
Une chose que vous devez réaliser est que dans Ruby tout est un object. Étant donné que si vous ne définissez pas vos méthodes dans Module
ou Class
, Ruby les placera dans la classe Object
. Ainsi, votre code sera local à la scope de l’ Object
.
Une approche typique de la programmation orientée object consiste à encapsuler toute la logique d’une classe:
class Point attr_accessor :x, :y # If we don't specify coordinates, we start at 0. def initialize(x = 0, y = 0) # Notice that `@` indicates instance variables. @x = x @y = y end # Here we override the `+' operator. def +(point) Point.new(self.x + point.x, self.y + point.y) end # Here we draw the point. def draw(offset = nil) if offset.nil? new_point = self else new_point = self + offset end new_point.draw_absolute end def draw_absolute puts "x: #{self.x}, y: #{self.y}" end end first_point = Point.new(100, 200) second_point = Point.new(3, 4) second_point.draw(first_point)
J’espère que cela clarifie un peu.
La scope variable dans Ruby est contrôlée par les sigils dans une certaine mesure. Les variables commençant par $
sont globales, les variables avec @
sont des variables d’instance, @@
signifie des variables de classe et les noms commençant par une majuscule sont des constantes. Toutes les autres variables sont locales. Lorsque vous ouvrez une classe ou une méthode, il s’agit d’une nouvelle étendue et les locaux disponibles dans la scope précédente ne sont pas disponibles.
Je préfère généralement éviter de créer des variables globales. Deux techniques permettent généralement d’atteindre le même objective que je considère plus propre:
Créez une constante dans un module. Donc, dans ce cas, vous devez placer toutes les classes qui ont besoin du décalage dans le module Foo
et créer un Offset
constant, de sorte que toutes les classes puissent accéder à Foo::Offset
.
Définir une méthode pour accéder à la valeur. Vous pouvez définir la méthode globalement, mais encore une fois, je pense qu’il est préférable de l’encapsuler dans un module ou une classe. De cette manière, les données sont disponibles là où vous en avez besoin et vous pouvez même les modifier si nécessaire, mais la structure de votre programme et la propriété des données seront plus claires. Ceci est plus conforme aux principes de conception OO.
L’une des raisons pour lesquelles la variable globale a besoin d’un préfixe ( $
) est que, dans Ruby, contrairement à C, vous n’avez pas besoin de déclarer vos variables avant de leur atsortingbuer un préfixe spécifique pour les globales offset = Point.new(100, 200)
dans votre méthode de dessin, alors Ruby ne saurait pas si vous vous référiez à la variable existante ou si vous créez une nouvelle variable locale dans votre méthode. Même chose avec le préfixe @
pour les variables d’instance.
Je pense que c’est local au fichier que vous avez déclaré offset. Considérez chaque fichier comme une méthode elle-même.
Peut-être mettre le tout dans une classe puis faire une variable de classe avec @@offset = Point.new(100, 200);
?