Ruby – classi e oggetti II

r3

Oggi si continua con gli oggetti.

Metodi privati

I metodi (funzioni in una classe) sono per default pubblici, cioè possono essere utilizzati al di fuori della classe, in qualsiasi parte dello script. Se si desidera che un metodo possa essere chiamato solo all’interno della classe in cui è definito bisogna dichiararlo privato, esempio:

#!/usr/bin/ruby
# encoding: UTF-8

# pm0.rb

class Human
    attr_accessor :name, :age

    def dimmi_di_te
        puts "Ciao, sono #{@name}. E ho #{@age} anni."
    end

    private
    def dimmi_un_segreto
        puts "Non sono umano, sono un robot\n" +
             "costruito dalla Sirius Cybernetics Corporation."
    end
end

h = Human.new
h.name = "Marvin"
h.age = 31419265
h.dimmi_di_te
h.dimmi_un_segreto #questo non funziona

pm0

Ecco, non funziona per via della chiamata a dimmi_un_segreto (riga 24) dichiarato private (riga 13).

Conviene dichiarare privati certi metodi per semplificare la programmazione; vediamo come modificare il programma precedente e accedere al metodo dimmi_un_segreto:

#!/usr/bin/ruby
# encoding: UTF-8

# pm0.rb

class Human
    attr_accessor :name, :age

    def dimmi_di_te
        puts "Ciao, sono #{@name}. E ho #{@age} anni."
    end

    def confessa
        dimmi_un_segreto
    end

    private
    def dimmi_un_segreto
        puts "Non sono umano, sono un robot\n" +
             "costruito dalla Sirius Cybernetics Corporation."
    end
end

h = Human.new
h.name = "Marvin"
h.age = 31419265
h.dimmi_di_te
h.confessa

pm1

OK, il metodo confessa (riga 28) è pubblico e possiamo usarlo nel main. Questo metodo chiama (riga 14) dimmi_un_segreto, metodo privato, ma può farlo perché è all’interno della classe Human, comune a entrambi i metodi. Con questo script così semplice sembra non ci sia nessun vantaggio ma nei casi reali le cose cambiano, eccome!

Variabili di classe e metodi

Finora abbiamo creato una classe e abbiamo visto che questa può avere attributi (come name e age) e funzioni (metodi) che possono essere chiamati da istanze alla classe (gli oggetti, h negli esempi precedenti).
Vediamo ora come chiamare una funzione senza dichiarare una variabile di quella classe.
Nel seguente esempio creiamo la classe Robot e usiamo la variabile @@robot_count che memorizza il numero di robot che sono stati creati. Siccome è una variabile di classe (class variable) il nome deve iniziare con @@.

#!/usr/bin/ruby
# encoding: UTF-8

# vm0.rb

class Robot
    def initialize
        if defined?(@@robot_count)
            @@robot_count += 1
        else
            @@robot_count = 1
        end
    end

    def self.robots_created
        @@robot_count
    end
end

r1 = Robot.new
r2 = Robot.new
puts "Creati #{Robot.robots_created} robot"

r3, r4, r5 = Robot.new, Robot.new, Robot.new
puts "Creati #{Robot.robots_created} robot"

vm0

Ho creato la funzione robot_created che ritorna il numero di robot che sono stati creati; notare che è scritta come self.robots_created dove la keyword self indica che la funzione può essere chiamata senza indicare l’oggetto a cui si riferisce, è cioè una variabile di classe.

Inoltre defined? (riga 8) è un predicato (funzione booleana) che verifica se la variabile è già esistente.
Karthikeyan, la guida che sto seguendo per questi post su Ruby, fa un esempio per far vedere un errore che salto, il tutto per dire che le variabili di classe non devono essere dichiarate come attr_reader.

Ereditarietà

Come nel mondo reale nella programmazione c’è l’eredità, una classe può avere proprietà prese (ereditate) da un’altra, con variazioni piccole o grandi.
Vediamo un esempio: i quadrati sono rettangoli con tutti i lati uguali, allora ecco:

#!/usr/bin/ruby
# encoding: UTF-8

# rq.rb

class Rettangolo
    attr_accessor :lunghezza, :larghezza

    def initialize lunghezza, larghezza
        @lunghezza = lunghezza
        @larghezza = larghezza
    end

    def area
        @lunghezza * @larghezza
    end

    def perimetro
        2 * (@lunghezza + @larghezza)
    end
end

class Quadrato < Rettangolo
    def initialize lunghezza
        @larghezza = @lunghezza = lunghezza
    end
end

q = Quadrato.new 5
puts "Il perimetro del quadrato q è #{q.perimetro}"
r = Rettangolo.new 3, 5
puts "L'area del rettangolo r è #{r.area}"

rq

Abbiamo definito la classe Rettangolo con due attributi, lunghezza e larghezza. che usiamo per i metodi area e perimetro di questa classe. Abbiamo poi definito la classe Quadrato che eredita le proprietà di Rettangolo (con < Rettangolo, riga 23). Per questa classe dobbiamo solo dire che lunghezza e larghezza sono uguali (riga 25), il calcolo di area e perimetro restano quelli ereditati e non dobbiamo riscriverli.

(Nota: Karthikeyan mette altri metodi, non usati che ho tolto per rendere l’esempio più semplice).

Siccome ci sono ancora tante cose da raccontare per oggi basta, continuiamo prossimamente 😉 🙂

Posta un commento o usa questo indirizzo per il trackback.

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo di WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google photo

Stai commentando usando il tuo account Google. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.

%d blogger hanno fatto clic su Mi Piace per questo: