Ruby Language
Klassen
Suche…
Syntax
- Klassenname
- #einiger Code, der das Klassenverhalten beschreibt
- Ende
Bemerkungen
Klassennamen in Ruby sind Konstanten, daher sollte der erste Buchstabe ein Großbuchstabe sein.
class Cat # correct
end
class dog # wrong, throws an error
end
Eine Klasse erstellen
Sie können eine neue Klasse mit dem Schlüsselwort class
.
class MyClass
end
Nach der Definition können Sie eine neue Instanz mit der .new
Methode .new
somevar = MyClass.new
# => #<MyClass:0x007fe2b8aa4a18>
Konstrukteur
Eine Klasse kann nur einen Konstruktor haben, dh eine Methode namens initialize
. Die Methode wird automatisch aufgerufen, wenn eine neue Instanz der Klasse erstellt wird.
class Customer
def initialize(name)
@name = name.capitalize
end
end
sarah = Customer.new('sarah')
sarah.name #=> 'Sarah'
Klassen- und Instanzvariablen
Es gibt verschiedene spezielle Variablentypen, mit denen eine Klasse Daten leichter austauschen kann.
Instanzvariablen mit vorangestelltem @
. Sie sind nützlich, wenn Sie dieselbe Variable in verschiedenen Methoden verwenden möchten.
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
Klassenvariable, vorangestellt mit @@
. Sie enthalten in allen Instanzen einer Klasse die gleichen Werte.
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
Globale Variablen, denen $
vorangestellt ist. Diese stehen überall im Programm zur Verfügung, stellen Sie also sicher, dass Sie diese sinnvoll einsetzen.
$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
Zugriff auf Instanzvariablen mit Gettern und Setters
Wir haben drei Methoden:
-
attr_reader
:attr_reader
dasread
der Variablen außerhalb der Klasse. -
attr_writer
:attr_writer
verwendet, um die Variable außerhalb der Klasse zuattr_writer
. -
attr_accessor
: kombiniert beide Methoden.
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
Beachten Sie, dass die Parameter Symbole sind. Dies funktioniert durch Erstellen einer Methode.
class Cat
attr_accessor :breed
end
Ist im Grunde dasselbe wie:
class Cat
def breed
@breed
end
def breed= value
@breed = value
end
end
Zugriffsebenen
Ruby hat drei Zugriffsebenen. Sie sind public
, private
und protected
.
Methoden, die den private
oder protected
Schlüsselwörtern folgen, sind als solche definiert. Methoden, die davor kommen, sind implizit public
Methoden.
Öffentliche Methoden
Eine öffentliche Methode sollte das Verhalten des erstellten Objekts beschreiben. Diese Methoden können außerhalb des Bereichs des erstellten Objekts aufgerufen werden.
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
Diese Methoden sind öffentliche Ruby-Methoden. Sie beschreiben das Verhalten beim Initialisieren einer neuen Katze und das Verhalten der Speak-Methode.
public
Schlüsselwort ist nicht erforderlich, kann jedoch zum protected
private
oder protected
def MyClass
def first_public_method
end
private
def private_method
end
public
def second_public_method
end
end
Private Methoden
Private Methoden sind nicht außerhalb des Objekts verfügbar. Sie werden intern vom Objekt verwendet. Wieder mit dem Katzenbeispiel:
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">
Wie Sie im obigen Beispiel sehen können, hat das neu erstellte Cat-Objekt intern Zugriff auf die Methode calculate_cat_age
. Wir weisen die Variable age
dem Ergebnis der Ausführung der privaten calculate_cat_age
Methode zu, die den Namen und das Alter der Katze an die Konsole ausgibt.
Wenn wir versuchen, die calculate_cat_age
Methode außerhalb des my_cat
Objekts my_cat
, erhalten wir einen NoMethodError
da er privat ist. Kapiert?
Geschützte Methoden
Geschützte Methoden sind privaten Methoden sehr ähnlich. Sie können nicht auf dieselbe Weise wie private Methoden außerhalb der Instanz des Objekts aufgerufen werden. Mit der self
Ruby-Methode können geschützte Methoden jedoch im Kontext eines Objekts desselben Typs aufgerufen werden.
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>
Sie können sehen, dass wir der Klasse cat einen Altersparameter hinzugefügt und drei neue Katzenobjekte mit Namen und Alter erstellt haben. Wir werden die own_age
protected-Methode own_age
, um das Alter unserer own_age
zu vergleichen.
cat1 == cat2
=> false
cat1 == cat3
=> true
Sehen Sie sich das an, wir konnten das Alter von self.own_age
mit der geschützten Methode self.own_age
und mit dem Alter von cat2.own_age
vergleichen, indem Sie cat2.own_age
in cat1 aufrufen.
Klassenmethoden-Typen
Klassen haben drei Arten von Methoden: Instanz-, Singleton- und Klassenmethoden.
Instanzmethoden
Dies sind Methoden, die von einer instance
der Klasse aus aufgerufen werden können.
class Thing
def somemethod
puts "something"
end
end
foo = Thing.new # create an instance of the class
foo.somemethod # => something
Klassenmethode
Dies sind statische Methoden, dh sie können für die Klasse und nicht für eine Instanziierung dieser Klasse aufgerufen werden.
class Thing
def Thing.hello(name)
puts "Hello, #{name}!"
end
end
Es ist gleichbedeutend mit self
anstelle des Klassennamens. Der folgende Code entspricht dem obigen Code:
class Thing
def self.hello(name)
puts "Hello, #{name}!"
end
end
Rufen Sie die Methode durch Schreiben auf
Thing.hello("John Doe") # prints: "Hello, John Doe!"
Singleton-Methoden
Diese stehen nur bestimmten Instanzen der Klasse zur Verfügung, jedoch nicht allen.
# 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>
Sowohl die singleton
und class
Methoden aufgerufen eigenclass
es. Grundsätzlich ist das Erstellen von anonymen Klassen, die solche Methoden enthalten, so dass Ruby die erstellten Instanzen nicht beeinträchtigt.
Eine andere Möglichkeit dazu ist der Konstruktor der class <<
. Zum Beispiel:
# 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"
Dynamische Klassenerstellung
Klassen können durch die Verwendung von Class.new
dynamisch erstellt werden.
# create a new class dynamically
MyClass = Class.new
# instantiate an object of type MyClass
my_class = MyClass.new
Im obigen Beispiel wird eine neue Klasse erstellt und der Konstante MyClass
zugewiesen. Diese Klasse kann wie jede andere Klasse instanziiert und verwendet werden.
Die Class.new
Methode akzeptiert eine Class
die zur Oberklasse der dynamisch erstellten Klasse wird.
# 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
Die Class.new
Methode akzeptiert auch einen Block. Der Kontext des Blocks ist die neu erstellte Klasse. Dadurch können Methoden definiert werden.
Duck =
Class.new do
def quack
'Quack!!'
end
end
# instantiate an object of type Duck
duck = Duck.new
duck.quack # 'Quack!!'
Neu, zuteilen und initialisieren
In vielen Sprachen werden neue Instanzen einer Klasse mit einem speziellen new
Schlüsselwort erstellt. In Ruby wird new
auch zum Erstellen von Instanzen einer Klasse verwendet, es ist jedoch kein Schlüsselwort. Stattdessen handelt es sich um eine statische / Klassenmethode, die sich nicht von anderen statischen / Klassenmethoden unterscheidet. Die Definition ist ungefähr so:
class MyClass
def self.new(*args)
obj = allocate
obj.initialize(*args) # oversimplied; initialize is actually private
obj
end
end
allocate
führt die eigentliche "Magie" der Erstellung einer nicht initialisierten Instanz der Klasse aus
Beachten Sie auch, dass der Rückgabewert von initialize
verworfen wird und stattdessen obj zurückgegeben wird. Dadurch wird sofort klar, warum Sie Ihre initialize-Methode codieren können, ohne sich am Ende das self
zu müssen.
Die 'normale' new
Methode, die alle Klassen von Class
funktioniert wie oben, aber es ist möglich, sie nach Belieben neu zu definieren oder Alternativen zu definieren, die anders funktionieren. Zum Beispiel:
class MyClass
def self.extraNew(*args)
obj = allocate
obj.pre_initialize(:foo)
obj.initialize(*args)
obj.post_initialize(:bar)
obj
end
end