Ruby – classi e oggetti IV

r5

Riflessione (reflection).

Ecco una parola difficile, per un concetto abbastanza particolare che forse in questa esposizione elementare si potrebbe anche saltare.
Intanto riporto la definizione presa da Wikipedia:

In informatica, la riflessione o reflection è la capacità di un programma di eseguire elaborazioni che hanno per oggetto il programma stesso, e in particolare la struttura del suo codice sorgente.

Per queste cose Ruby è OK, tutto è un oggetto e è stato influenzato anche dal Lisp, l’ideale in questo campo. L’articolo di Wikipedia è da leggere, altrimenti il rischio di non capire è forte. Ho anche provato a riassumerlo, tentativo non riuscito, leggetelo di là.

OK, un accenno, vediamo, con l’interprete interattivo:

r0

la risposta è molto più lunga, quello che voglio illustrare è che methods ritorna l’elenco dei metodi della stringa; perché a è una stringa, vero?

r1

Proviamo allora a definire una classe, e vedere come funziona per essa la riflessione (refl.rb):

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

# refl.rb

class Qualcheclasse
    attr_accessor :a, :b

    private
    def private_method
    end

    protected
    def protected_method
    end

    public
    def public_method
    end
end

qualcosa = Qualcheclasse.new
qualcosa.a = 'a'
qualcosa.b = 123

puts "qualcosa appartiene a #{qualcosa.class}"
puts
puts "qualcosa ha le seguenti variabili d'istanza:"
puts qualcosa.instance_variables.join(', ')
puts
puts "qualcosa ha i seguenti metodi:"
puts qualcosa.methods.join(', ')
puts
puts "qualcosa ha i seguenti metodi pubblici:"
puts qualcosa.public_methods.join(', ')
puts
puts "qualcosa ha i seguenti metodi privati:"
puts qualcosa.private_methods.join(', ')
puts
puts "qualcosa ha i seguenti metodi protetti:"
puts qualcosa.protected_methods.join(', ')

Eseguendolo con il comando ruby refl.rb otteniamo un output kilometrico, questo:

qualcosa appartiene a Qualcheclasse

qualcosa ha le seguenti variabili d’istanza:
@a, @b

qualcosa ha i seguenti metodi:
a, a=, b, b=, protected_method, public_method, nil?, ===, =~, !~, eql?, hash, , class, singleton_class, clone, dup, initialize_dup, initialize_clone, taint, tainted?, untaint, untrust, untrusted?, trust, freeze, frozen?, to_s, inspect, methods, singleton_methods, protected_methods, private_methods, public_methods, instance_variables, instance_variable_get, instance_variable_set, instance_variable_defined?, instance_of?, kind_of?, is_a?, tap, send, public_send, respond_to?, respond_to_missing?, extend, display, method, define_singleton_method, object_id, to_enum, enum_for, ==, equal?, !, !=, instance_eval, instance_exec, __send__, __id__

qualcosa ha i seguenti metodi pubblici:
a, a=, b, b=, public_method, nil?, ===, =~, !~, eql?, hash, , class, singleton_class, clone, dup, initialize_dup, initialize_clone, taint, tainted?, untaint, untrust, untrusted?, trust, freeze, frozen?, to_s, inspect, methods, singleton_methods, protected_methods, private_methods, public_methods, instance_variables, instance_variable_get, instance_variable_set, instance_variable_defined?, instance_of?, kind_of?, is_a?, tap, send, public_send, respond_to?, respond_to_missing?, extend, display, method, define_singleton_method, object_id, to_enum, enum_for, ==, equal?, !, !=, instance_eval, instance_exec, __send__, __id__

qualcosa ha i seguenti metodi privati:
private_method, initialize_copy, remove_instance_variable, sprintf, format, Integer, Float, String, Array, warn, raise, fail, global_variables, __method__, __callee__, eval, local_variables, iterator?, block_given?, catch, throw, loop, caller, trace_var, untrace_var, at_exit, syscall, open, printf, print, putc, puts, gets, readline, select, readlines, `, p, test, srand, rand, trap, exec, fork, exit!, system, spawn, sleep, exit, abort, load, require, require_relative, autoload, autoload?, proc, lambda, binding, set_trace_func, Rational, Complex, gem, gem_original_require, initialize, singleton_method_added, singleton_method_removed, singleton_method_undefined, method_missing

qualcosa ha i seguenti metodi protetti:
protected_method

OK? Notare l’uso di join (che concatena le stringhe) per l’output. Forse della riflessione dovremo parlarne ancora.

Incapsulazione

capsula

Avete presente quelle medicine contenute in una capsula come quelle in figura? Ecco un concetto simile esiste nella programmazione OOP, quindi in Ruby. L’incapsulazione serve a nascondere i dettagli quando questi non sono richiesti, facilitando la scrittura e la manutenzione del codice. Esattamente come la vostra auto: quello che vi serve è la chiave d’accensione e il volante, non v’interessa cosa c’è sotto il cofano, almeno non dovrebbe.

Ecco un esempio (incap.rb):

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

# incap.rb

class Human
    attr_reader :firstname, :lastname

    def name=(name)
        @firstname, @lastname = name.split
    end
end

me = Human.new
me.name = "Juhan vanJuhan"
puts "   Nome: #{me.firstname}"
puts "Cognome: #{me.lastname}"

incap

Notare che in questo modo firstname e lastname possono essere assegnati solo attraverso il metodo name di Human. Scrivere firstname = "Juhan" darebbe un errore.

Notare inoltre che lo script non funziona con i carabinieri e per il Poli di Torino (e probabilmente anche per altre organizzazioni). Non funziona neanche con i nomi cinesi, giapponesi e ungheresi. E quelli composti. Insomma dovreste riscriverlo 😉 meglio.

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: