Ruby'de Soyut Veri Tipleri
Ruby soyut veri tipleri için desteği “sınıf” yapısı ile verir. Ruby sınıfları kabiliyetleri bakımından C++ ve Java sınıfları ile benzerlik gösterir [6]. İleriki bölümlerde soyut veri tiplerinin özellikleri, nesneye yönelik programlama ile birlikte verilecektir.
Ruby'de Nesneye Yönelik Programlama
Ruby nesneye yönelik bir programlama dili olarak tasarlanmıştır ve saf bir nesneye yönelik programlama dili olarak görülür. Ruby'de her şey bir nesne olarak görünür. Ruby'deki karakter katarı, sayı ve mantıksal ifadeler gibi en basit veri tiplerinin değerleri bilenesne olarak tutulur [1,2,3].
puts 1.class => "Fixnum"
puts true.class => "TrueClass"
puts nil.class => "NilClass"
|
Sınıf Tanımı
Ruby’de sınıflar “class” anahtar kelimesi ve sonrasında gelen büyük harf ile başlayan bir isimle tanımlanır ve Ruby'deki bir çok yapı gibi “end” ifadesi ile tanım sonlandırılır [2]. Aşağıda basit bir sınıf tanımı görülmektedir:
class RubyClass
end
|
- Sınıf İlklendirmesi / Nesne Oluşturulması
Ruby’de tanımlanan bir sınıftan “new” sayesinde nesne oluşturulabilir [4].
ruby1 = RubyClass.new
ruby1.is_a? RubyClass # => true
|
Bir sınıf ilk defa ilklendirildiğinde initialize yapılandırıcı metodu çağrılır [4].
class RubyClass2
def initialize(value1, value2, value3)
@v1 = value1
@v2 = value2
@v3 = value3
end
end
|
Sınıftan nesne oluşturulurken “new”e geçirilen her parametre initialize metoduna aktarılır ve ilklendirmede kullanılır. Metod aşırı yükleme (overloading) RubY'de bulunmadığından bir sınıfın sadece bir yapılandırıcı initialize metodu vardır.
ruby2 = RubyClass2.new(1,2,3)
|
- Değişken Tipleri ve Erişim Yöntemleri
Örnek (instance) değişkenler @ ile başlarlar ve nesneye aittirler. Etki alanı self nesnesi ile yani oluşturulan nesne ile sınırlıdır. Değerleri diğer nesnelerle paylaşılmaz. Nesne dışından erişilemez. Erişim için değişkene özgü metod tanımlanmalıdır [4]. Ruby'de değişkenlerin tanımlanmasına gerek yoktur.
class RubyClass3
def initialize(value1)
@v1 = value1
end
# Erişim metodu (getter)
def v1
@v1
end
# Değer verme metodu (setter)
def v1(value1)
@v1 = value1
end
# Sınıf içinden sınıf değişkene self ile erişilebilir
def v1reset
self.v1 = 0;
end
end
|
ruby3 = RubyClass3.new(1)
puts ruby3.v1 # => 3
|
Örnek değişkenlere erişim metodları otomatik oluşturulabilir. “att_reader” anahtar kelimesi sayesinde sadece erişim metodu tanımlanırken, “att_accessor” anahtar kelimesi sayesinde sadece erişim metodu tanımlanır [4].
class RubyClass4
attr_accessor :v1;
end
|
Sınıf değişkenleri yani tüm nesneler tarafından paylaşılan değişkenler ise @@ ile başlarlar. Bir sınıfı miras alan alt sınıflar tarafından da erişilebilirler [5].
Sınıf sabitleri ise büyük harfle başlarlar ve yanlızca bir defa değer atamasına izin vardır.ğer yeniden değer ataması yapılırsa, hata değil uyarı mesajı verilir. Sabitler sınıfla beraber tanımlanmalıdır ancak, örnek değişkenlerin aksine sınıf ismiyle beraber belirtilerek (Ör. sinif::SABIT şeklinde) sınıfın dışından da erişilebilirler [5].
Yerel değişkenler ise küçük harfle ya da “_” karakteriyle başlar. Yerel değişkenler genel ya da örnek değişkenlerde olduğu gibi, başlangıçta nil değerine sahip değildirler, çünkü atama yapmadan gerçekte oluşmazlar. Yerel bir değişkene yaptığınız ilk atama onu bildirmekle aynı şeydir. Eğer başlangıç değeri olmayan bir yerel değişkene başvurursanız, Ruby yorumlayıcısı bunun bir yöntemi çalıştırma girişimi olduğunu düşünür ve hata verir [5].
- Erişim Kontrolü / Bilgi Saklama (Information Hiding)
Ruby'de public, private ve protected olmak üzere 3 tip erişim kontrolü tanımlanmıştır. Bunlar önüne geldikleri değişkenin erişim özelliğini değiştirirler. Ruby'de ön tanımlı oalrak metodlar “public”, değişkenler ise “private” dır [2].
- Public : Erişim her yerden sağlanabileceğini belirtir.
- Private: Erişimin nesne içinde kısıtlandığını belirtir.
- Protected: Erişimi alt sınıflardan da mümkün kılar.
Miras
Ruby'de alt sınıf tanımı yapılırken üst sınıftan miras “<” sembolü sayesinde gerçekleştirilir. Üst sınıftaki metodlar ve değişkenler alt sınıf tarafından miras alınırlar [7].
class RubyClass5A
def initialize(value1)
@v1 = value1
end
end
class RubyClass5B < RubyClass5A
def initialize(value2)
@v2 = @v1 + value2
end
end
|
Ruby'de çoklu miras desteklenmez [5].
- Method Ezme (Overriding)
Ruby'de üst sınıfta tanımlanmış bir metod aynı şekilde alt sınıfta tanımlanırsa, alt sınıf için üst sınıftaki metodun tanımı geçersiz yapılıp yenisi tanımlanmış olur [2].
class RubyClass6A
def metodX
puts “6A”
end
end
class RubyClass6B < RubyClass6A
def metodX
puts “6B”
end
end
|
- Operatör Yeniden Tanımlama (Overloading)
Ruby'de hem standart tipler için hem de programcı tanımlı sınıflar için operator yeniden tanımlanması (overloading) mümkündür [2].
class Kutu
def initialize(en,boy)
@en,@boy = en, boy
end
def +(diger)
Kutu.new(@en + diger.en, @boy + diger.boy)
end
def -@
Box.new(-@en, -@boy)
end
def *(sayi)
Box.new(@en*sayi, @boy*sayi)
end
end
|
Ara Yüz (Interface)
Ruby soyut sınıfları veya ara yüz (interface) tanımlamayı desteklemez [6]. Bununla beraber, her ne kadar gerçek bir ara yüz tanımının yerini tutmasa da, Ruby'deki mevcut sınıfları kullanılarak interface benzeri yapılar oluşturmak mümkündür [7,8].
class Dil
def merhaba
raise NotImplementedError
end
end
class Turkce < Dil
def merhaba
puts "Merhaba"
end
end
|
İsimlendirme Sarmalaması (Naming-Encapsulation) Yapıları
Ruby'de modül (module) yapılarının örneği ve alt sınıfı tanımlanamaz. Ruby modülleri bir isimlendirme sarmalı oluşturmak için sıklıkla kullanılır ve fonksiyonların bir kütüphanesini oluşturmak için faydalıdır. Bir modülün kullanılabilmesi için modül “requşre” anahtar kelimesi ile belirtilir. Modüllerin fonksiyonlarına direk erişim mümkündür. Bu nedenle bir nevi çoklu miras bu şekilde sağlanır [6].
Dinamik Bağlama
Ruby dinamik tip tanımlı bir dildir. Değişkenler bir tipe sahip değildir, aslında değişkenler her hangi bir sınıfın nesnesine referans verirler. Bir değişken her hangi bir sınıfa referans verebildiği için aslında çok yüzlülük (polymorphism) sağlanmış olur [6].
[1] "Ruby Programming Language”, http://en.wikipedia.org/wiki/Ruby_(programming_language), Erişim: 27 Mayıs 2014.
[2] “Object Oriented Ruby”, http://www.tutorialspoint.com/ruby/ruby_object_oriented.htm, Erişim: 27 Mayıs 2014.
[3] “Ruby Programming/Data Types”, Wikibooks, http://en.wikibooks.org/wiki/Ruby_Programming/Data_types. Erişim Tarihi: 24 Nisan 2014.
[4] Flanagan D., Matsumoto Y., The Ruby Programming Language, O'Reilly Media, 2008.
[5] M. Slagell and P. Yanardağ, "Ruby Kullanıcı Kılavuzu," 22 Nisan 2003. [Çevrimiçi]. Available: http://pdf.belgeler.org/uygulamalar/ruby/ruby-ug.pdf, Erişim Tarihi: 27 Mayıs 2014.
[6] Sebesta, R.W., Concepts of Programming Languages, Pearson Education, 2012.
[7] “Ruby Interfaces”, http://briancarper.net/blog/226/. Erişim Tarihi: 27 Mayıs 2014.
[8] “What is java interface equivalent in Ruby?”, http://stackoverflow.com/questions/4437291/what-is-java-interface-equivalent-in-ruby. Erişim Tarihi: 27 Mayıs 2014.
NOT: YTÜ - İleri Programlama Dili Dersi 2014 1. Dönem Ödevi Çerçevesinde Hazırlanmıştır.
NOT 2: Ruby 1.9 baz alınmıştır.