Im Kern ist Ruby eine objektorientierte Sprache. Alles ist ein Objekt. Yukihiro „Matz“ Matsumoto hat seine Sprache allerdings ähnlich wie C++ als „Multiparadigmen-Sprache“ entworfen. Das ermöglicht Software Entwicklern unter anderem funktionale (es gibt anonyme Funktionen, Closures und Continuations; Alle Ausdrücke haben einen Wert und Funktionen returnieren die letzte Auswertung), prozedurale (Variablen und Funktionen die ausserhalb einer Klasse definiert werden sind automatisch Teil des Root Objektes) als auch objektorientierte (alles ist ein Objekt) Programmierparadigmen einzusetzen. Weiters unterstützt Ruby auch Introspection, Reflection und Metaprogramming. Im Folgenden werden Beispiele der am weitesten verbreiteten Paradigmen gezeigt:

Objektorientierte Programmierung

In der Sprache Ruby ist alles ein Objekt: Jeder Datentyp ist ein Objekt. Auch Klassen und solche, die in vielen anderen Sprachen als primitive Datentypen gelten, wie etwa Integer, Booleans oder nil. Jede Funktion ist eine Methode. Alle Variablen sind Referenzen zu Objekten und nicht selbst Objekte.

Klassenbasierte Objektorientierung

Eine Klasse kann wie folgt definiert werden:

   1  class Bird
   2    def sing
   3     puts "singing"
   4    end
   5  end
   6  
   7  >> Bird.class
   8  => Class

Klassen werden mit dem Keyword Class definiert. Methoden mit dem Keyword def. Hier sieht man auch, dass die Klasse Bird selbst eine Objekt vom Typ Class ist.

   1  >> my_bird = Bird.new
   2  => #<Bird:0x1016d0360>
   3  >> my_bird.class
   4  => Bird
   5  >> my_bird.class.superclass
   6  => Object

Ein Objekt wird mit der Methode .new erzeugt. Die Ausgabe zeigt dass die Variable my_bird auf ein Objekt der Klasse Bird verweist und automatisch ein Kind von Object ist.

   1  my_bird.sing
   2  singing
   3  => nil

Eine Methode wird einfach auf dem Objekt aufgerufen.

Eine Ableitung wird so definiert:

   1  class FlyingBird < Bird
   2    def fly
   3      puts "flying"
   4    end
   5  end
   6   
   7  >> my_flying_bird = FlyingBird.new
   8  => #<FlyingBird:0x1016bbd48>
   9  >> my_flying_bird.fly
  10  flying
  11  => nil
  12  >> my_flying_bird.sing
  13  singing
  14  => nil
  15  >> my_flying_bird.class
  16  => FlyingBird
  17  >> my_flying_bird.class.superclass
  18  => Bird

my_flying_bird ist also ein Kind von Bird und Bird ist ein Kind von Object. FlyingBird erbt alle Methoden der Klasse Bird (unter anderem auch sing). Zusätzlich wird für FlyingBird noch die Methode fly definiert.

Prototypenbasierte Objektorientierung

Ruby bietet auch die von JavaScript oder Io bekannte prototypenbasierte Objektorientierung.

Das obige Beispiel mit Prototypen realisiert:

   1  ?> my_bird = Object.new
   2  => #<Object:0x101662c48>
   3  >> def my_bird.sing
   4  >>   puts "singing"
   5  >> end
   6  => nil
   7  >>  
   8  ?> my_bird.sing
   9  singing
  10  => nil
  11  >>  
  12  ?> my_flying_bird = my_bird.clone
  13  => #<Object:0x101656dd0>
  14  >> def my_flying_bird.fly
  15  >>   puts "flying"
  16  >> end
  17  => nil
  18  >>  
  19  ?> my_flying_bird.sing
  20  singing
  21  => nil
  22  >> my_flying_bird.fly
  23  flying
  24  => nil

Objektorientierung mit Mixins

Ruby bietet keine Mehrfachvererbung. Das heisst man kann in Ruby nicht von mehr als einer Klasse erben. Das stellt aber keine Einschränkung dar, da mit Modulen und Mixins ein eigenens Konzept existiert, um Implementierungen allgemein für Klassen zur Verfügung zu stellen.

In Ruby sind Mixins Module, die in andere Objekte eingebunden werden. Hier eine Implementierung des obigen Beispiels mit Modulen und Mixins:

   1  module Communication
   2    def sing
   3      puts "singing"
   4    end
   5  end
   6   
   7  module Movement
   8    def fly
   9      puts "flying"
  10    end
  11  end
  12  
  13  class Bird
  14    include Communication
  15  end
  16   
  17  class FlyingBird < Bird
  18    include Movement
  19  end
  20  
  21  ?> my_bird = Bird.new
  22  => #<Bird:0x10162c418>
  23  >> my_flying_bird = FlyingBird.new
  24  => #<FlyingBird:0x101628f98>
  25  >> 
  26  ?> my_bird.sing
  27  singing
  28  => nil
  29  >> 
  30  ?> my_flying_bird.sing
  31  singing
  32  => nil
  33  >> my_flying_bird.fly
  34  flying
  35  => nil

Auch die protoypische Variante lässt sich mit Mixins und Modulen umsetzen

   1  my_flying_bird = Object.new
   2  my_flying_bird.extend Communication
   3  my_flying_bird.extend Movement
   4  
   5  ?> my_flying_bird.sing
   6  singing
   7  => nil
   8  >> my_flying_bird.fly
   9  flying
  10  => nil

Prozedurale Programmierung

Auch die Prozedurale Syntax wird von Ruby unterstützt. Allerdings muss man beachten, dass alle Methoden Definitionen, die ausserhalb einer Klasse vorgenommen werden, automatisch Methoden der Klasse Object – der Mutter aller Objekte – werden. Das hat zur Folge, dass diese Methoden auch in allen anderen Objekten und Klassen sichtbar sind (und schlimmstenfalls eine bestehende Methode der Klasse Object überschreiben!)

Das einfachste Hello World Programm kann somit als:

   1  def hello_world
   2    puts "Hello World!"
   3  end
   4  
   5  ?> hello_world
   6  Hello World!

definiert werden.

Die Konsequenz kann wie folgt veranschaulicht werden:

   1  class Dummy; end
   2  >> dummy = Dummy.new
   3  => #<Dummy:0x1015e6d00>
   4  >> dummy.hello_world
   5  Hello World!
   6  >> dummy.to_s
   7  => "#<Dummy:0x1015e6d00>"
   8  
   9  def to_s
  10    "my to_s"
  11  end
  12  
  13  >> dummy.to_s
  14  my to_s

Da jede Methode, die nicht im Kontext einer Klasse oder eines Objektes definiert wird automatisch Teil der Basisklasse Object wird, kann es einem schnell passieren unerwünschte Seiteneffekte zu erzielen.

Funktionale Programmierung

In Ruby hat jeder Ausdruck einen Wert. Das kann dafür genutzt werden Probleme funktional zu lösen:

Das folgendende Beispiel zeigt ein case-Konstrukt, das je nach Wert der Variable option einen anderen Wert zurück liefert.

   1  option = "array"
   2  result = case option
   3            when "number"   then 1
   4            when "string"  then "Got a String"
   5            when "array" then ["I", "am", "a", "Array"]
   6            else raise "unknown option"
   7          end
   8  => ["I", "am", "a", "Array"]        

In Ruby kann man auch Lambda Konstrukte definieren. Mit einem Lambda-Konstrukt kann man einen Codeblock in einer Funktionsvariablen speichern.

   1  print_function = lambda { |item| print item + 1 }
   2  [1,2,3].each &print_function
   3  234=> [1, 2, 3]
blog comments powered by Disqus

related Articles:

Deployment of Java Web Applications with Chef from Opscode

There is a rework of the data driven deployment of java web applications. This Vagrant project on github ( https://github.com/iteh/vagrant-demos/ ) showcases the application cookbook for chef with a reworked application definition and LWRP for...

Links der Woche vom 2011-05-23 bis 2011-05-29

Diese Woche Links zu den Themen Windows, Ruby, opscode, JavaScript, maps, Leaflet, WordPress, Chef, windows, powershell, opschef, ios, ruby, devops, sysadmin, monitoringsucks

Links der Woche vom 2011-05-16 bis 2011-05-22

Diese Woche Links zu den Themen coffeebeans, Rails, CoffeeScript, Array, Ruby, Chef, Django, zo, devops, sysadmin, git, chef, CSS3, HTML5, WordPress, nipplegate, MongoDB, rails, rails3, asciicast, test, Android, opschef, Gem, aws, slim, Haml, ruby

Links der Woche vom 2011-05-09 bis 2011-05-15

Diese Woche Links zu den Themen wi, opschef, ActiveAdmin, rails, ror, ruby, HTML5, Chef, cnet, MongoDB, Sinatra, Rack, apple, git, aws, chef, opscode, sysadmin, Ksplice, noSQL, RubyTutorials, CSS3, EC2, AWS, MacRuby, iOS, m

Links der Woche vom 2011-04-11 bis 2011-04-17

Diese Woche Links zu den Themen ipad, iphone, opschef, ruby, OpenCV, detection, image, Weinberg, Ohai, automation, pr, test, gem, cloudfoundry, devops, cfoundry

Data Driven Deployment of a Java Web Application with Chef Solo

Chef Application Cookbook Showcase This Vagrant project on github ( https://github.com/iteh/vagrant-demos/ ) showcases the application cookbook for chef

Links der Woche vom 2011-04-04 bis 2011-04-10

Diese Woche Links zu den Themen Pow, Rack, ActiveRecord, Rails, Algorithms, Ruby, rails, optimize, CSS3, railscasts, chat, macbook, opschef, ruby

Links der Woche vom 2011-03-21 bis 2011-03-27

Diese Woche Links zu den Themen MacRuby, Java, Ruby, Mirah, CSS, refreshtoplayagain, gainsboro, photo, Design, mechanize, capybara, PHP, Rails, html5, webdesign, XCode, iPads, WordPress, Vagrant, Opscode, RUBY, Selenium, php, opschef, osx, devops,...

Links der Woche vom 2011-03-14 bis 2011-03-20

Diese Woche Links zu den Themen opschef, chef, mwrc, saas, Subscription, Billing, git, ruby, HTTP, Rails, Caching, devops, vagrant, opscode, Wordpress

Wordpress über JSON Api mit Facebook Page oder Tumblr befüllen

In diesem Beispiel zeigen wir die Installation von Wordpress in einem Ubuntu LAMP Stack. Weiters wird das JSON-Api Plugin für Wordpress und ein Theme installiert. Danach wird mit Mechanize der Wordpress Blog automatisch installiert und...