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:

  1. attr_reader : permet de read la variable en dehors de la classe.
  2. attr_writer : permet de modifier la variable en dehors de la classe.
  3. 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


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow