Ruby Objektorientiert

Ruby ist eine rein objektorientierte Sprache, und alles in Ruby hat die Form von Objekten. Jeder Wert in Ruby ist ein Objekt, sogar die primitivsten Dinge: Zeichenketten, Zahlen und sogar true und false sind Objekte. Die Klasse selbst ist auch einObjekt, dieClasseine Instanz der Klasse Class ist. Dieses Kapitel erläutert alle Hauptmerkmale der objektorientierten Programmierung in Ruby.

Klassen werden verwendet, um die Form von Objekten festzulegen. Sie kombinieren Datenrepräsentation und Methoden und organisieren Daten in einem sauberen Paket. Die Daten und Methoden in einer Klasse werden Mitglieder der Klasse genannt.

Ruby-Klassendefinition

Wenn Sie eine Klasse definieren, definieren Sie tatsächlich einen Bauplan für einen Datentyp. Dies definiert eigentlich keine Daten, sondern legt fest, was der Klassenname bedeutet, das heißt, woraus die Objekte der Klasse bestehen und welche Operationen auf dem Objekt ausgeführt werden können.

Eine Klassendefinition beginnt mit dem Schlüsselwortclassund darauf folgtder Klassenname, und endet schließlich mitendein Trennzeichen, um das Ende der Klassendefinition zu markieren. Zum Beispiel verwenden wir das Schlüsselwort class, um die Klasse Box zu definieren, wie unten gezeigt:

class Box code end

Üblicherweise muss der Name mit einem Großbuchstaben beginnen. Wenn er mehrere Wörter enthält, wird der erste Buchstabe jedes Wortes großgeschrieben, jedoch ohne Trennzeichen dazwischen (z. B. CamelCase).

Ruby-Objekte definieren

Klassen liefern den Bauplan für Objekte, daher werden Objekte im Grunde auf Grundlage der Klasse erstellt. Wir verwenden das Schlüsselwortnew, um Objekte der Klasse zu deklarieren. Die folgende Anweisung deklariert zwei Objekte der Klasse Box:

box1 = Box.new box2 = Box.new

Die initialize-Methode

initializeDie Methode ist eine standardmäßige Ruby-Klassenmethode, dient als Klassenkonstruktor und ähnelt dem Arbeitsprinzip desKonstruktorsin anderen objektorientierten Programmiersprachen. Wenn Sie beim Erstellen eines Objekts einige Klassenvariablen initialisieren möchten, ist die initialize-Methode hilfreich. Diese Methode nimmt eine Reihe von Parametern entgegen; wie bei anderen Ruby-Methoden müssen Sie bei ihrer Verwendung dasdef-Schlüsselwort davor setzen, wie unten gezeigt:

class Box def initialize(w,h) @width, @height = w, h end end

Instanzvariablen

Instanzvariablensind Klassenattribute. Wenn Objekte mit der Klasse erstellt werden, werden sie zu den Attributen der Objekte. Die Attribute jedes Objekts werden separat zugewiesen und teilen keine Werte mit anderen Objekten. Innerhalb der Klasse wird auf diese Attribute mit dem @-Operator zugegriffen; außerhalb der Klasse wird auf sie mit Methoden namensAccessor-Methoden, dievonöffentlichenMethoden sind. Unten nehmen wir die oben definierte KlasseBoxals Beispiel und verwenden @width und @height als Instanzvariablen der Klasse Box.

class Box def initialize(w,h) #Werte an Instanzvariablen zuweisen @width, @height = w, h end end

Accessor-(Getter-) & Setter-(Setter-)Methoden

Um Variablen, die in einer Klasse definiert sind, von außerhalb der Klasse zu lesen, können wir Accessor-(Getter-)Methoden definieren, um auf sie zuzugreifen. Das folgende Beispiel zeigt die Verwendung von Accessor-Methoden:

Beispiel

#!/usr/bin/ruby -w #Definiere die Klasse class Box #Konstruktor def initialize(w,h) @width, @height = w, h end #Accessor-Methoden def printWidth @width end def printHeight @height end end #Erzeuge ein Objekt und initialisiere die Höhe und Breite der Box box = Box.new(10, 20) #Accessor-Methoden verwenden x = box.printWidth() y = box.printHeight() puts "Box-Breite : #{x}" puts "Box-Höhe : #{y}"

Ausprobieren »

Wenn der obige Code ausgeführt wird, erzeugt er das folgende Ergebnis:

盒子宽度 : 10
盒子高度 : 20

Ähnlich wie Accessor-Methoden, die verwendet werden, um auf Variablenwerte zuzugreifen, bietet Ruby eine Möglichkeit, Parameter von außerhalb der Klasse an in einer Klasse definierte Variablen zu übergeben, die sogenanntenSetter-Methoden, die wie folgt definiert sind:

Beispiel

#!/usr/bin/ruby -w #Definiere die Klasse class Box #Konstruktormethode def initialize(w,h) @width, @height = w, h end #Accessor-Methoden def getWidth @width end def getHeight @height end #Setter-Methoden def setWidth=(value) @width = value end def setHeight=(value) @height = value end end #Objekte erstellen box = Box.new(10, 20) #Setter-Methoden verwenden box.setWidth = 30 box.setHeight = 50 #Accessor-Methoden verwenden x = box.getWidth() y = box.getHeight() puts "Box-Breite : #{x}" puts "Box-Höhe : #{y}"

Ausprobieren »

Wenn der obige Code ausgeführt wird, erzeugt er das folgende Ergebnis:

盒子宽度 : 30
盒子高度 : 50

Da beide Methoden sehr häufig verwendet werden, definiert Rubyattr_accessor :variable_name, attr_reader :variable_name, attr_writer :variable_namedrei Methoden zur Attributdeklaration. Darunter:accessor=reader+writer。

Beachte außerdem: Der Variablenname muss mit:beginnen, und zwischen Variablennamen verwendet man,zur Trennung.

Instanzmethoden

Instanzmethodenwerden genauso wie andere Methoden definiert, und zwar mit demdefSchlüsselwort, aber sie können nur über Klasseninstanzen verwendet werden, wie im folgenden Beispiel gezeigt. Ihre Funktionen sind nicht auf den Zugriff auf Instanzvariablen beschränkt; sie können auch viele andere Aufgaben nach Bedarf ausführen.

Beispiel

#!/usr/bin/ruby -w #Definiere die Klasse class Box #Konstruktormethode def initialize(w,h) @width, @height = w, h end #Instanzmethode def getArea @width * @height end end #Objekte erstellen box = Box.new(10, 20) #Die Instanzmethode aufrufen a = box.getArea() puts "Die Fläche der Box ist : #{a}"

Ausprobieren »

Wenn der obige Code ausgeführt wird, erzeugt er das folgende Ergebnis:

Area of the box is : 200

Klassenmethoden & Klassenvariablen

Klassenvariablensind Variablen, die von allen Instanzen einer Klasse gemeinsam genutzt werden. Mit anderen Worten, auf Klassenvariablen kann von allen Objektinstanzen zugegriffen werden. Klassenvariablen wird ein Präfix aus zwei @-Zeichen (@@) vorangestellt. Klassenvariablen müssen in der Klassendefinition initialisiert werden, wie im folgenden Beispiel gezeigt.

Klassenmethodenwerden mit demdef self.methodname()Schlüsselwort definiert, und Klassenmethoden enden mit dem End-Delimiter. Klassenmethoden können unter Verwendung derclassname.methodname-Form mit dem Klassennamen aufgerufen werden, wie im folgenden Beispiel gezeigt:

Beispiel

#!/usr/bin/ruby -w class Box #Klassenvariablen initialisieren @@count = 0 def initialize(w,h) #Werte den Instanzvariablen zuweisen @width, @height = w, h @@count += 1 end def self.printCount() puts "Box-Anzahl ist : #@@count" end end #Zwei Objekte erstellen box1 = Box.new(10, 20) box2 = Box.new(30, 100) #Klassenmethode aufrufen, um die Box-Anzahl auszugeben Box.printCount()

Ausprobieren »

Wenn der obige Code ausgeführt wird, erzeugt er das folgende Ergebnis:

Box count is : 2

Die to_s-Methode

Jede Klasse, die Sie definieren, hat eineto_s-Instanzmethode, um die Zeichenfolgendarstellung des Objekts zurückzugeben. Das Folgende ist ein einfaches Beispiel, das Box-Objekte anhand von Breite und Höhe darstellt:

Beispiel

#!/usr/bin/ruby -w class Box #Konstruktormethode def initialize(w,h) @width, @height = w, h end #Definiere die to_s-Methode def to_s "(w:#@width,h:#@height)" #Das Zeichenkettenformat des Objekts end end #Objekte erstellen box = Box.new(10, 20) #Die to_s-Methode wird automatisch aufgerufen puts "Stringdarstellung von box ist: #{box}"

Ausprobieren »

Wenn der obige Code ausgeführt wird, erzeugt er das folgende Ergebnis:

String representation of box is : (w:10,h:20)

Zugriffskontrolle

Ruby bietet Ihnen drei Stufen des Instanzmethodenschutzes, nämlichpublic, private oder protected. Ruby wendet keine Zugriffskontrolle auf Instanz- und Klassenvariablen an.

  • Öffentliche Methoden:Öffentliche Methoden können von jedem Objekt aufgerufen werden. Standardmäßig sind Methoden öffentlich, mit Ausnahme der initialize-Methode, die immer privat ist.
  • Private Methoden:Man kann von außerhalb der Klasse nicht auf private Methoden zugreifen oder sie einsehen. Nur Klassenmethoden können auf private Member zugreifen.
  • Geschützte Methoden:Geschützte Methoden können nur von Objekten der Klasse und ihrer Unterklassen aufgerufen werden. Der Zugriff kann auch nur innerhalb der Klasse und ihrer Unterklassen erfolgen.

Das Folgende ist ein einfaches Beispiel, das die Syntax dieser drei Modifikatoren demonstriert:

Beispiel

#!/usr/bin/ruby -w #Definiere die Klasse class Box #Konstruktormethode def initialize(w,h) @width, @height = w, h end #Instanzmethoden sind standardmäßig öffentlich def getArea getWidth() * getHeight end #Definieren Sie private Zugriffsmethoden def getWidth @width end def getHeight @height end # Machen Sie sie privat private :getWidth, :getHeight #Eine Instanzmethode zur Ausgabe der Fläche def printArea @area = getWidth() * getHeight puts "Die Fläche der großen Box ist: #@area" end #Machen Sie die Instanzmethode geschützt protected :printArea end #Erstellen Sie Objekte box = Box.new(10, 20) #Rufen Sie Instanzmethoden auf a = box.getArea() puts "Die Fläche der Box ist : #{a}" #Versuchen Sie, die geschützte Instanzmethode aufzurufen box.printArea()

Ausprobieren »

Wenn der obige Code ausgeführt wird, erzeugt er das folgende Ergebnis. Hier ist der erste Methodenaufruf erfolgreich, aber die zweite Methode verursacht ein Problem.

Area of the box is : 200
test.rb:42: protected method `printArea' called for #
<Box:0xb7f11280 @height=20, @width=10> (NoMethodError)

Klassenvererbung

Vererbung ist eines der wichtigsten Konzepte in der objektorientierten Programmierung. Vererbung ermöglicht es uns, eine Klasse auf Basis einer anderen Klasse zu definieren, was das Erstellen und Warten von Anwendungen erleichtert.

Vererbung hilft bei der Wiederverwendung von Code und einer schnellen Ausführung. Leider unterstützt Ruby keine Mehrfachvererbung, aber Ruby unterstütztMixinsMixins. Mixins sind wie eine spezielle Implementierung von Mehrfachvererbung, bei der nur der Schnittstellenteil vererbbar ist.

Wenn eine Klasse erstellt wird, kann der Programmierer direkt angeben, dass die neue Klasse die Mitglieder einer vorhandenen Klasse erbt, wodurch vermieden wird, neue Datenmitglieder und Mitgliedsfunktionen von Grund auf neu zu schreiben. Diese vorhandene Klasse wirdBasisklasse oder Elternklasse genannt, und die neue Klasse wirdabgeleitete Klasse oder Unterklasse genannt。

Ruby bietet auch das Konzept der Unterklassenbildung, was Vererbung ist. Das folgende Beispiel erklärt dieses Konzept. Die Syntax zum Erweitern einer Klasse ist sehr einfach. Fügen Sie einfach ein < Zeichen und den Namen der Elternklasse zur class-Anweisung hinzu. Zum Beispiel definiert das Folgende die KlasseBigBoxJaBoxUnterklasse:

Beispiel

#!/usr/bin/ruby -w #Klasse definieren class Box #Konstruktormethode def initialize(w,h) @width, @height = w, h end #Instanzmethode def getArea @width * @height end end #Unterklasse definieren class BigBox < Box #Eine neue Instanzmethode hinzufügen def printArea @area = @width * @height puts "Die Fläche der großen Box ist : #@area" end end #Objekt erstellen box = BigBox.new(10, 20) #Fläche ausgeben box.printArea()

Ausprobieren »

Wenn der obige Code ausgeführt wird, erzeugt er das folgende Ergebnis:

Big box area is : 200

Methodenüberladung

Obwohl du in einer abgeleiteten Klasse neue Funktionalität hinzufügen kannst, möchtest du manchmal das Verhalten einer Methode ändern, die bereits in der Elternklasse definiert ist. In diesem Fall kannst du den Methodennamen unverändert lassen und die Funktionalität der Methode überschreiben, wie im folgenden Beispiel gezeigt:

Beispiel

#!/usr/bin/ruby -w #Klasse definieren class Box #Konstruktormethode def initialize(w,h) @width, @height = w, h end #Instanzmethode def getArea @width * @height end end #Unterklasse definieren class BigBox < Box #Die vorhandene getArea-Methode ändern def getArea @area = @width * @height puts "Die Fläche der großen Box ist : #@area" end end #Objekt erstellen box = BigBox.new(10, 20) #Verwende die überschriebene Methode, um die Fläche auszugeben box.getArea()

Ausprobieren »

Die Ausgabe des obigen Beispiels ist:

Big box area is : 200

Operatorüberladung

Wir möchten den +-Operator verwenden, um eine Vektoraddition zweier Box-Objekte durchzuführen, den *-Operator verwenden, um Breite und Höhe von Box zu multiplizieren, und den unären Operator - verwenden, um Breite und Höhe von Box zu negieren. Unten ist eine Version der Box-Klasse mit Definitionen mathematischer Operatoren:

class Box def initialize(w,h) #Breite und Höhe initialisieren @width,@height = w, h end def +(other) #Definiere +, um Vektoraddition durchzuführen Box.new(@width + other.width, @height + other.height) end def -@ #Definiere den unären Operator -, um Breite und Höhe zu negieren Box.new(-@width, -@height) end def *(scalar) #Skalarmultiplikation durchführen Box.new(@width*scalar, @height*scalar) end end

Objekte einfrieren

Manchmal möchten wir verhindern, dass Objekte geändert werden. In Object kann die Methode freeze dies erreichen und ein Objekt effektiv in eine Konstante verwandeln. Jedes Objekt kann eingefroren werden, indem manObject.freezefreeze aufruft. Ein eingefrorenes Objekt kann nicht geändert werden, das heißt, du kannst seine Instanzvariablen nicht ändern.

Du kannst dieObject.frozen?-Methode verwenden, um zu prüfen, ob ein gegebenes Objekt eingefroren wurde. Wenn das Objekt eingefroren ist, gibt diese Methode true zurück; andernfalls gibt sie einen false-Wert zurück. Das folgende Beispiel erläutert dieses Konzept:

Beispiel

#!/usr/bin/ruby -w #Klasse definieren class Box #Konstruktormethode def initialize(w,h) @width, @height = w, h end #Zugriffsmethode def getWidth @width end def getHeight @height end #Setter-Methode def setWidth=(value) @width = value end def setHeight=(value) @height = value end end #Objekt erstellen box = Box.new(10, 20) #Lass uns das Objekt einfrieren box.freeze if( box.frozen? ) puts "Box-Objekt ist ein eingefrorenes Objekt" else puts "Box-Objekt ist ein normales Objekt" end #Versuchen Sie nun, die Setter-Methode zu verwenden box.setWidth = 30 box.setHeight = 50 #Verwenden Sie die Zugriffsmethode x = box.getWidth() y = box.getHeight() puts "Breite der Box ist : #{x}" puts "Höhe der Box ist : #{y}"

Ausprobieren »

Wenn der obige Code ausgeführt wird, erzeugt er das folgende Ergebnis:

Box object is frozen object
test.rb:20:in `setWidth=': can't modify frozen object (TypeError)
        from test.rb:39

Klassenkonstanten

Sie können eine Konstante innerhalb einer Klasse definieren, indem Sie einer Variable einen direkten numerischen oder String-Wert zuweisen. Konstanten müssen nicht @ oder @@ verwenden. Üblicherweise werden Konstantennamen großgeschrieben.

Sobald eine Konstante definiert ist, können Sie ihren Wert nicht ändern. Sie können direkt innerhalb der Klasse auf die Konstante zugreifen, genau wie auf eine Variable, aber wenn Sie von außerhalb der Klasse auf die Konstante zugreifen möchten, müssen Sieclassname::constant:: verwenden, wie im folgenden Beispiel gezeigt.

Beispiel

#!/usr/bin/ruby -w #Klasse definieren class Box BOX_COMPANY = "TATA Inc" BOXWEIGHT = 10 #Konstruktormethode def initialize(w,h) @width, @height = w, h end #Instanzmethode def getArea @width * @height end end #Objekt erstellen box = Box.new(10, 20) #Instanzmethode aufrufen a = box.getArea() puts "Die Fläche der Box ist : #{a}" puts Box::BOX_COMPANY puts "Box weight is: #{Box::BOXWEIGHT}"

Ausprobieren »

Wenn der obige Code ausgeführt wird, erzeugt er das folgende Ergebnis:

Area of the box is : 200
TATA Inc
Box weight is: 10

Klassenkonstanten können vererbt werden und können auch wie Instanzmethoden überschrieben werden.

Objekte mit allocate erstellen

Es kann eine Situation geben, in der Sie ein Objekt erstellen möchten, ohne den Objektkonstruktorinitializeaufzurufen, d. h. ohne die Methode new zum Erstellen eines Objekts zu verwenden. In diesem Fall können Sie allocate aufrufen, um ein nicht initialisiertes Objekt zu erstellen, wie im folgenden Beispiel gezeigt:

Beispiel

#!/usr/bin/ruby -w #Klasse definieren class Box attr_accessor :width, :height #Konstruktormethode def initialize(w,h) @width, @height = w, h end #Instanzmethode def getArea @width * @height end end #Objekt mit new erstellen box1 = Box.new(10, 20) #Ein weiteres Objekt mit allocate erstellen box2 = Box.allocate #Instanzmethode mit box1 aufrufen a = box1.getArea() puts "Area of the box is : #{a}" #Instanzmethode mit box2 aufrufen a = box2.getArea() puts "Die Fläche der Box ist: #{a}"

Ausprobieren »

Wenn der obige Code ausgeführt wird, erzeugt er das folgende Ergebnis:

Area of the box is : 200
test.rb:14: warning: instance variable @width not initialized
test.rb:14: warning: instance variable @height not initialized
test.rb:14:in `getArea': undefined method `*' 
   for nil:NilClass (NoMethodError) from test.rb:29

Klasseninformation

Rubys self und Javas this haben Ähnlichkeiten, unterscheiden sich aber auch deutlich. In Java werden Methoden innerhalb von Instanzmethoden referenziert, daher verweist this im Allgemeinen auf das aktuelle Objekt. Rubys Code wird Zeile für Zeile ausgeführt, daher hat self in verschiedenen Kontexten unterschiedliche Bedeutungen. Betrachten wir das folgende Beispiel:

Beispiel

#!/usr/bin/ruby -w class Box #Klasseninformationen ausgeben puts "Klasse von self = #{self.class}" puts "Name von self = #{self.name}" end

Ausprobieren »

Wenn der obige Code ausgeführt wird, erzeugt er das folgende Ergebnis:

Class of self = Class
Name of self = Box

Das bedeutet, dass die Klassendefinition ausgeführt werden kann, indem die Klasse als aktuelles Objekt behandelt wird, und es bedeutet auch, dass die Methoden in der Metaklasse und der Elternklasse während der Ausführung der Methodendefinition verfügbar sind.

Andere Erweiterungen