Ricerca…


Sintassi

  • nome della classe
  • # Qualche codice che descrive il comportamento della classe
  • fine

Osservazioni

I nomi delle classi in Ruby sono Costanti, quindi la prima lettera dovrebbe essere una maiuscola.

class Cat # correct
end  

class dog # wrong, throws an error
end

Creare una classe

Puoi definire una nuova classe usando la parola chiave class .

class MyClass
end

Una volta definiti, è possibile creare una nuova istanza utilizzando il .new metodo

somevar = MyClass.new
# => #<MyClass:0x007fe2b8aa4a18>

Costruttore

Una classe può avere un solo costruttore, ovvero un metodo chiamato initialize . Il metodo viene automaticamente richiamato quando viene creata una nuova istanza della classe.

class Customer
  def initialize(name)
     @name = name.capitalize 
  end
end

sarah = Customer.new('sarah')
sarah.name #=> 'Sarah'

Classi e variabili di istanza

Esistono diversi tipi di variabili speciali che una classe può utilizzare per condividere più facilmente i dati.

Variabili di istanza, precedute da @ . Sono utili se si desidera utilizzare la stessa variabile con metodi diversi.

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

Variabile di classe, preceduta da @@ . Contengono gli stessi valori su tutte le istanze di una 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

Variabili globali, precedute da $ . Questi sono disponibili ovunque per il programma, quindi assicurati di usarli con saggezza.

$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

Accesso alle variabili di istanza con getter e setter

Abbiamo tre metodi:

  1. attr_reader : utilizzato per consentire la read della variabile al di fuori della classe.
  2. attr_writer : usato per consentire la modifica della variabile al di fuori della classe.
  3. attr_accessor : combina entrambi i metodi.
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

Si noti che i parametri sono simboli. questo funziona creando un metodo.

class Cat
  attr_accessor :breed
end

È fondamentalmente lo stesso di:

class Cat
  def breed
    @breed
  end
  def breed= value
    @breed = value
  end
end

Livelli di accesso

Ruby ha tre livelli di accesso. Sono public , private e protected .

I metodi che seguono le parole chiave private o protected sono definiti come tali. I metodi che precedono questi sono metodi implicitamente public .

Metodi pubblici

Un metodo pubblico dovrebbe descrivere il comportamento dell'oggetto che si sta creando. Questi metodi possono essere richiamati dall'esterno dell'oggetto creato.

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

Questi metodi sono metodi ruby ​​pubblici, descrivono il comportamento per l'inizializzazione di un nuovo gatto e il comportamento del metodo speak.

public parola chiave public non è necessaria, ma può essere utilizzata per sfuggire a private o protected

def MyClass
  def first_public_method
  end

  private

  def private_method
  end

  public

  def second_public_method
  end
end

Metodi privati

I metodi privati ​​non sono accessibili dall'esterno dell'oggetto. Sono usati internamente dall'oggetto. Usando di nuovo l'esempio del gatto:

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">

Come puoi vedere nell'esempio sopra, l'oggetto Cat appena creato ha accesso al metodo calculate_cat_age internamente. Assegniamo l' age variabile al risultato dell'esecuzione del metodo private calculate_cat_age che stampa il nome e l'età del gatto sulla console.

Quando proviamo a chiamare il metodo calculate_cat_age dall'esterno dell'oggetto my_cat , riceviamo un NoMethodError perché è privato. Prendilo?

Metodi protetti

I metodi protetti sono molto simili ai metodi privati. Non è possibile accedere al di fuori dell'istanza dell'oggetto nello stesso modo in cui i metodi privati ​​non possono essere. Tuttavia, usando il metodo self ruby, i metodi protetti possono essere chiamati all'interno del contesto di un oggetto dello stesso tipo.

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>

Puoi vedere che abbiamo aggiunto un parametro età alla classe cat e creato tre nuovi oggetti gatto con il nome e l'età. Chiameremo il metodo protetto own_age per confrontare l'età dei nostri oggetti gatto.

cat1 == cat2
=> false

cat1 == cat3
=> true

Guardate questo, siamo stati in grado di recuperare l'età di cat1 usando il metodo protetto self.own_age e confrontarlo con l'età di cat2.own_age chiamando cat2.own_age all'interno di cat1.

Tipi di metodi di classe

Le classi hanno 3 tipi di metodi: istanza, singleton e metodi di classe.

Metodi di istanza

Questi sono metodi che possono essere chiamati da instance della classe.

class Thing
  def somemethod
    puts "something"
  end
end

foo = Thing.new # create an instance of the class
foo.somemethod # => something

Metodo di classe

Questi sono metodi statici, cioè possono essere richiamati sulla classe e non su un'istanza di quella classe.

class Thing
  def Thing.hello(name)
    puts "Hello, #{name}!"
  end
end

È equivalente usare self al posto del nome della classe. Il seguente codice è equivalente al codice sopra:

class Thing
  def self.hello(name)
    puts "Hello, #{name}!"
  end
end

Invoca il metodo scrivendo

Thing.hello("John Doe")  # prints: "Hello, John Doe!"

Metodi Singleton

Questi sono disponibili solo per istanze specifiche della classe, ma non per tutti.

# 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>

Entrambi i metodi singleton e class sono chiamati eigenclass es. Fondamentalmente, ciò che ruby ​​fa è creare una classe anonima che contiene tali metodi in modo che non interferisca con le istanze che vengono create.

Un altro modo per farlo è il costruttore della class << . Per esempio:

# 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"

Creazione di classi dinamiche

Le classi possono essere create dinamicamente attraverso l'uso di Class.new .

# create a new class dynamically
MyClass = Class.new

# instantiate an object of type MyClass
my_class = MyClass.new

Nell'esempio sopra, una nuova classe viene creata e assegnata alla costante MyClass . Questa classe può essere istanziata e utilizzata come qualsiasi altra classe.

Il metodo Class.new accetta una Class che diventerà la superclasse della classe creata dinamicamente.

# 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

Il metodo Class.new accetta anche un blocco. Il contesto del blocco è la classe appena creata. Ciò consente di definire metodi.

Duck = 
  Class.new do
    def quack
      'Quack!!'
    end
  end

# instantiate an object of type Duck
duck = Duck.new
duck.quack # 'Quack!!'

Nuovo, allocare e inizializzare

In molte lingue, vengono create nuove istanze di una classe utilizzando una new parola chiave speciale. In Ruby, new viene anche usato per creare istanze di una classe, ma non è una parola chiave; invece, è un metodo statico / di classe, non diverso da qualsiasi altro metodo statico / di classe. La definizione è all'incirca questa:

class MyClass
   def self.new(*args)
     obj = allocate
     obj.initialize(*args) # oversimplied; initialize is actually private
     obj
   end
end

allocate esegue la vera 'magia' di creare un'istanza non inizializzata della classe

Si noti inoltre che il valore di ritorno di initialize viene scartato e invece viene restituito obj. Questo rende immediatamente chiaro il motivo per cui puoi codificare il tuo metodo di inizializzazione senza preoccuparti di restituire te self alla fine.

Il new metodo "normale" che tutte le classi ottengono da Class funziona come sopra, ma è possibile ridefinirlo come più ti piace o definire alternative che funzionano in modo diverso. Per esempio:

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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow