Ruby Language
Des classes
Recherche…
Syntaxe
- nom du cours
- #some code décrivant le comportement de la classe
- fin
Remarques
Les noms de classe dans Ruby sont des constantes, donc la première lettre devrait être une majuscule.
class Cat # correct
end
class dog # wrong, throws an error
end
Créer une classe
Vous pouvez définir une nouvelle classe en utilisant le mot class
clé class
.
class MyClass
end
Une fois défini, vous pouvez créer une nouvelle instance en utilisant la méthode .new
somevar = MyClass.new
# => #<MyClass:0x007fe2b8aa4a18>
Constructeur
Une classe ne peut avoir qu'un seul constructeur, c'est-à-dire une méthode appelée initialize
. La méthode est automatiquement appelée lorsqu'une nouvelle instance de la classe est créée.
class Customer
def initialize(name)
@name = name.capitalize
end
end
sarah = Customer.new('sarah')
sarah.name #=> 'Sarah'
Variables de classe et d'instance
Il existe plusieurs types de variables spécifiques qu'une classe peut utiliser pour partager plus facilement des données.
Variables d'instance, précédées de @
. Ils sont utiles si vous souhaitez utiliser la même variable dans différentes méthodes.
class Person
def initialize(name, age)
my_age = age # local variable, will be destroyed at end of constructor
@name = name # instance variable, is only destroyed when the object is
end
def some_method
puts "My name is #{@name}." # we can use @name with no problem
end
def another_method
puts "My age is #{my_age}." # this will not work!
end
end
mhmd = Person.new("Mark", 23)
mhmd.some_method #=> My name is Mark.
mhmd.another_method #=> throws an error
Variable de classe, précédée de @@
. Ils contiennent les mêmes valeurs sur toutes les instances d'une classe.
class Person
@@persons_created = 0 # class variable, available to all objects of this class
def initialize(name)
@name = name
# modification of class variable persists across all objects of this class
@@persons_created += 1
end
def how_many_persons
puts "persons created so far: #{@@persons_created}"
end
end
mark = Person.new("Mark")
mark.how_many_persons #=> persons created so far: 1
helen = Person.new("Helen")
mark.how_many_persons #=> persons created so far: 2
helen.how_many_persons #=> persons created so far: 2
# you could either ask mark or helen
Variables globales, précédées de $
. Ceux-ci sont disponibles partout dans le programme, alors assurez-vous de les utiliser à bon escient.
$total_animals = 0
class Cat
def initialize
$total_animals += 1
end
end
class Dog
def initialize
$total_animals += 1
end
end
bob = Cat.new()
puts $total_animals #=> 1
fred = Dog.new()
puts $total_animals #=> 2
Accès aux variables d'instance avec les getters et les setters
Nous avons trois méthodes:
-
attr_reader
: permet deread
la variable en dehors de la classe. -
attr_writer
: permet de modifier la variable en dehors de la classe. -
attr_accessor
: combine les deux méthodes.
class Cat
attr_reader :age # you can read the age but you can never change it
attr_writer :name # you can change name but you are not allowed to read
attr_accessor :breed # you can both change the breed and read it
def initialize(name, breed)
@name = name
@breed = breed
@age = 2
end
def speak
puts "I'm #{@name} and I am a #{@breed} cat"
end
end
my_cat = Cat.new("Banjo", "birman")
# reading values:
my_cat.age #=> 2
my_cat.breed #=> "birman"
my_cat.name #=> Error
# changing values
my_cat.age = 3 #=> Error
my_cat.breed = "sphynx"
my_cat.name = "Bilbo"
my_cat.speak #=> I'm Bilbo and I am a sphynx cat
Notez que les paramètres sont des symboles. Cela fonctionne en créant une méthode.
class Cat
attr_accessor :breed
end
Est fondamentalement la même chose que:
class Cat
def breed
@breed
end
def breed= value
@breed = value
end
end
Niveaux d'accès
Ruby a trois niveaux d'accès. Ils sont public
, private
et protected
.
Les méthodes qui suivent les mots-clés private
ou protected
sont définies comme telles. Les méthodes qui précèdent sont implicitement public
méthodes public
.
Méthodes publiques
Une méthode publique doit décrire le comportement de l'objet en cours de création. Ces méthodes peuvent être appelées en dehors de la portée de l'objet créé.
class Cat
def initialize(name)
@name = name
end
def speak
puts "I'm #{@name} and I'm 2 years old"
end
...
end
new_cat = Cat.new("garfield")
#=> <Cat:0x2321868 @name="garfield">
new_cat.speak
#=> I'm garfield and I'm 2 years old
Ces méthodes sont des méthodes publiques ruby, elles décrivent le comportement d’initialisation d’un nouveau chat et le comportement de la méthode speak.
mot-clé public
est inutile, mais peut être utilisé pour échapper private
ou protected
def MyClass
def first_public_method
end
private
def private_method
end
public
def second_public_method
end
end
Méthodes Privées
Les méthodes privées ne sont pas accessibles de l'extérieur de l'objet. Ils sont utilisés en interne par l'objet. En utilisant à nouveau l'exemple de chat:
class Cat
def initialize(name)
@name = name
end
def speak
age = calculate_cat_age # here we call the private method
puts "I'm #{@name} and I'm #{age} years old"
end
private
def calculate_cat_age
2 * 3 - 4
end
end
my_cat = Cat.new("Bilbo")
my_cat.speak #=> I'm Bilbo and I'm 2 years old
my_cat.calculate_cat_age #=> NoMethodError: private method `calculate_cat_age' called for #<Cat:0x2321868 @name="Bilbo">
Comme vous pouvez le voir dans l'exemple ci-dessus, l'objet Cat nouvellement créé a accès à la méthode calculate_cat_age
interne. Nous affectons l' age
variable au résultat de l'exécution de la méthode calculate_cat_age
privée qui imprime le nom et l'âge du chat sur la console.
Lorsque nous essayons d'appeler la méthode calculate_cat_age
dehors de l'objet my_cat
, nous recevons une NoMethodError
car elle est privée. Trouver?
Méthodes protégées
Les méthodes protégées sont très similaires aux méthodes privées. On ne peut pas y accéder en dehors de l'instance d'objet de la même manière que les méthodes privées ne peuvent pas l'être. Cependant, en utilisant la méthode self
ruby, les méthodes protégées peuvent être appelées dans le contexte d'un objet du même type.
class Cat
def initialize(name, age)
@name = name
@age = age
end
def speak
puts "I'm #{@name} and I'm #{@age} years old"
end
# this == method allows us to compare two objects own ages.
# if both Cat's have the same age they will be considered equal.
def ==(other)
self.own_age == other.own_age
end
protected
def own_age
self.age
end
end
cat1 = Cat.new("ricky", 2)
=> #<Cat:0x007fe2b8aa4a18 @name="ricky", @age=2>
cat2 = Cat.new("lucy", 4)
=> #<Cat:0x008gfb7aa6v67 @name="lucy", @age=4>
cat3 = Cat.new("felix", 2)
=> #<Cat:0x009frbaa8V76 @name="felix", @age=2>
Vous pouvez voir que nous avons ajouté un paramètre age à la classe cat et créé trois nouveaux objets chat avec le nom et l'âge. Nous allons appeler la méthode own_age
protected pour comparer l'âge de nos objets de chat.
cat1 == cat2
=> false
cat1 == cat3
=> true
Regardez cela, nous avons pu récupérer l'âge de cat1 en utilisant la méthode protégée self.own_age
et la comparer à l'âge de cat2.own_age
appelant cat2.own_age
intérieur de cat1.
Types de méthodes de classe
Les classes ont 3 types de méthodes: les méthodes instance, singleton et class.
Méthodes d'instance
Ce sont des méthodes qui peuvent être appelées à partir d'une instance
de la classe.
class Thing
def somemethod
puts "something"
end
end
foo = Thing.new # create an instance of the class
foo.somemethod # => something
Méthode de classe
Ce sont des méthodes statiques, c'est-à-dire qu'elles peuvent être invoquées sur la classe et non sur une instanciation de cette classe.
class Thing
def Thing.hello(name)
puts "Hello, #{name}!"
end
end
Cela équivaut à utiliser self
à la place du nom de la classe. Le code suivant est équivalent au code ci-dessus:
class Thing
def self.hello(name)
puts "Hello, #{name}!"
end
end
Invoquer la méthode en écrivant
Thing.hello("John Doe") # prints: "Hello, John Doe!"
Méthodes Singleton
Ceux-ci ne sont disponibles que pour des instances spécifiques de la classe, mais pas pour tous.
# create an empty class
class Thing
end
# two instances of the class
thing1 = Thing.new
thing2 = Thing.new
# create a singleton method
def thing1.makestuff
puts "I belong to thing one"
end
thing1.makestuff # => prints: I belong to thing one
thing2.makestuff # NoMethodError: undefined method `makestuff' for #<Thing>
Les méthodes singleton
et class
sont toutes deux appelées eigenclass
. Fondamentalement, Ruby crée une classe anonyme qui contient de telles méthodes afin de ne pas interférer avec les instances créées.
Une autre façon de faire est d' class <<
constructeur de class <<
. Par exemple:
# a class method (same as the above example)
class Thing
class << self # the anonymous class
def hello(name)
puts "Hello, #{name}!"
end
end
end
Thing.hello("sarah") # => Hello, sarah!
# singleton method
class Thing
end
thing1 = Thing.new
class << thing1
def makestuff
puts "I belong to thing one"
end
end
thing1.makestuff # => prints: "I belong to thing one"
Création de classe dynamique
Les classes peuvent être créées dynamiquement via l'utilisation de Class.new
.
# create a new class dynamically
MyClass = Class.new
# instantiate an object of type MyClass
my_class = MyClass.new
Dans l'exemple ci-dessus, une nouvelle classe est créée et affectée à la constante MyClass
. Cette classe peut être instanciée et utilisée comme toute autre classe.
La méthode Class.new
accepte une Class
qui deviendra la super-classe de la classe créée dynamiquement.
# dynamically create a class that subclasses another
Staffy = Class.new(Dog)
# instantiate an object of type Staffy
lucky = Staffy.new
lucky.is_a?(Staffy) # true
lucky.is_a?(Dog) # true
La méthode Class.new
accepte également un bloc. Le contexte du bloc est la classe nouvellement créée. Cela permet de définir des méthodes.
Duck =
Class.new do
def quack
'Quack!!'
end
end
# instantiate an object of type Duck
duck = Duck.new
duck.quack # 'Quack!!'
Nouveau, allouer et initialiser
Dans de nombreux langages, de nouvelles instances d'une classe sont créées à l'aide d'un new
mot-clé spécial. Dans Ruby, new
est également utilisé pour créer des instances d'une classe, mais ce n'est pas un mot clé; au lieu de cela, c'est une méthode statique / classe, pas différente de toute autre méthode statique / classe. La définition est à peu près ceci:
class MyClass
def self.new(*args)
obj = allocate
obj.initialize(*args) # oversimplied; initialize is actually private
obj
end
end
allocate
effectue la véritable «magie» de la création d'une instance non initialisée de la classe
Notez également que la valeur de retour de initialize
est ignorée et que obj est renvoyé à la place. Cela rend immédiatement clair pourquoi vous pouvez coder votre méthode initialize sans se soucier de retourner l' self
à la fin.
La new
méthode «normale» que toutes les classes obtiennent de Class
fonctionne comme ci-dessus, mais il est possible de la redéfinir comme vous le souhaitez ou de définir des alternatives qui fonctionnent différemment. Par exemple:
class MyClass
def self.extraNew(*args)
obj = allocate
obj.pre_initialize(:foo)
obj.initialize(*args)
obj.post_initialize(:bar)
obj
end
end