Ruby in zwanzig Minuten
Lassen Sie uns jetzt ein Greeter-Objekt erstellen und es verwenden
irb(main):035:0> greeter = Greeter.new("Pat")
=> #<Greeter:0x16cac @name="Pat">
irb(main):036:0> greeter.say_hi
Hi Pat!
=> nil
irb(main):037:0> greeter.say_bye
Bye Pat, come back soon.
=> nilSobald das greeter-Objekt erstellt ist, merkt es sich, dass der Name Pat ist. Hmm, was ist, wenn wir direkt auf den Namen zugreifen wollen?
irb(main):038:0> greeter.@name
SyntaxError: (irb):38: syntax error, unexpected tIVAR, expecting '('Nein, das geht nicht.
Unter der Haut des Objekts
Instanzvariablen sind im Objekt versteckt. Sie sind nicht besonders gut versteckt, Sie sehen sie, wenn Sie das Objekt inspizieren, und es gibt andere Möglichkeiten, auf sie zuzugreifen, aber Ruby verwendet den guten objektorientierten Ansatz, Daten irgendwie versteckt zu halten.
Welche Methoden gibt es also für Greeter-Objekte?
irb(main):039:0> Greeter.instance_methods
=> [:say_hi, :say_bye, :instance_of?, :public_send,
:instance_variable_get, :instance_variable_set,
:instance_variable_defined?, :remove_instance_variable,
:private_methods, :kind_of?, :instance_variables, :tap,
:is_a?, :extend, :define_singleton_method, :to_enum,
:enum_for, :<=>, :===, :=~, :!~, :eql?, :respond_to?,
:freeze, :inspect, :display, :send, :object_id, :to_s,
:method, :public_method, :singleton_method, :nil?, :hash,
:class, :singleton_class, :clone, :dup, :itself, :taint,
:tainted?, :untaint, :untrust, :trust, :untrusted?, :methods,
:protected_methods, :frozen?, :public_methods, :singleton_methods,
:!, :==, :!=, :__send__, :equal?, :instance_eval, :instance_exec, :__id__]Wow. Das sind viele Methoden. Wir haben nur zwei Methoden definiert. Was ist hier los? Nun, das sind **alle** Methoden für Greeter-Objekte, eine vollständige Liste, einschließlich derer, die von Elterklassen definiert wurden. Wenn wir nur Methoden auflisten wollen, die für Greeter definiert sind, können wir angeben, dass wir keine von Elterklassen definierten Methoden einschließen wollen, indem wir den Parameter false übergeben.
irb(main):040:0> Greeter.instance_methods(false)
=> [:say_hi, :say_bye]Ah, das ist besser. Lassen Sie uns also sehen, auf welche Methoden unser Greeter-Objekt reagiert
irb(main):041:0> greeter.respond_to?("name")
=> false
irb(main):042:0> greeter.respond_to?("say_hi")
=> true
irb(main):043:0> greeter.respond_to?("to_s")
=> trueEs kennt also say_hi und to_s (was bedeutet, etwas in einen String umwandeln, eine Methode, die standardmäßig für jedes Objekt definiert ist), aber es kennt name nicht.
Klassen ändern – Es ist nie zu spät
Aber was, wenn Sie den Namen sehen oder ändern möchten? Ruby bietet eine einfache Möglichkeit, auf die Variablen eines Objekts zuzugreifen.
irb(main):044:0> class Greeter
irb(main):045:1> attr_accessor :name
irb(main):046:1> end
=> [:name, :name=]In Ruby können Sie eine Klasse erneut öffnen und sie ändern. Die Änderungen werden in allen neuen Objekten, die Sie erstellen, vorhanden sein und sogar in bestehenden Objekten dieser Klasse verfügbar sein. Lassen Sie uns also ein neues Objekt erstellen und mit seiner @name-Eigenschaft spielen.
irb(main):047:0> greeter = Greeter.new("Andy")
=> #<Greeter:0x3c9b0 @name="Andy">
irb(main):048:0> greeter.respond_to?("name")
=> true
irb(main):049:0> greeter.respond_to?("name=")
=> true
irb(main):050:0> greeter.say_hi
Hi Andy!
=> nil
irb(main):051:0> greeter.name="Betty"
=> "Betty"
irb(main):052:0> greeter
=> #<Greeter:0x3c9b0 @name="Betty">
irb(main):053:0> greeter.name
=> "Betty"
irb(main):054:0> greeter.say_hi
Hi Betty!
=> nilDie Verwendung von attr_accessor hat zwei neue Methoden für uns definiert: name zum Abrufen des Werts und name= zum Festlegen.
Begrüßen von allem und jedem, MegaGreeter vernachlässigt niemanden!
Dieser Greeter ist aber nicht besonders interessant, er kann nur eine Person nach der anderen betreuen. Was ist, wenn wir eine Art MegaGreeter hätten, der entweder die Welt, eine Person oder eine ganze Liste von Personen begrüßen könnte?
Schreiben wir diesmal in eine Datei, anstatt direkt im interaktiven Ruby-Interpreter IRB.
Um IRB zu beenden, geben Sie "quit", "exit" ein oder drücken Sie einfach Control-D.
#!/usr/bin/env ruby
class MegaGreeter
attr_accessor :names
# Create the object
def initialize(names = "World")
@names = names
end
# Say hi to everybody
def say_hi
if @names.nil?
puts "..."
elsif @names.respond_to?("each")
# @names is a list of some kind, iterate!
@names.each do |name|
puts "Hello #{name}!"
end
else
puts "Hello #{@names}!"
end
end
# Say bye to everybody
def say_bye
if @names.nil?
puts "..."
elsif @names.respond_to?("join")
# Join the list elements with commas
puts "Goodbye #{@names.join(", ")}. Come back soon!"
else
puts "Goodbye #{@names}. Come back soon!"
end
end
end
if __FILE__ == $0
mg = MegaGreeter.new
mg.say_hi
mg.say_bye
# Change name to be "Zeke"
mg.names = "Zeke"
mg.say_hi
mg.say_bye
# Change the name to an array of names
mg.names = ["Albert", "Brenda", "Charles",
"Dave", "Engelbert"]
mg.say_hi
mg.say_bye
# Change to nil
mg.names = nil
mg.say_hi
mg.say_bye
endSpeichern Sie diese Datei als "ri20min.rb" und führen Sie sie als "ruby ri20min.rb" aus. Die Ausgabe sollte lauten:
Hello World!
Goodbye World. Come back soon!
Hello Zeke!
Goodbye Zeke. Come back soon!
Hello Albert!
Hello Brenda!
Hello Charles!
Hello Dave!
Hello Engelbert!
Goodbye Albert, Brenda, Charles, Dave, Engelbert. Come
back soon!
...
...
In diesem letzten Beispiel gibt es viele neue Dinge, die wir genauer betrachten können.