3. Sınıflar, yapılar, arayüzler
3.1. Örnek üzerinden nesne
3.1.1. Genel bilgiler
Şimdi örnek üzerinden nesne yönelimli programlamayı ele alacağız. Bir nesne, durumunu tanımlayan verileri (bunlara özellik denir) ve işlevleri (bunlara yöntem denir) içeren bir varlıktır. Bir nesne, sınıf adı verilen bir modele göre oluşturulur:
Public Class c1
' özellikler
Private p1 As type1
Private p2 As type2
....
' yöntem
Public Sub m1(....)
...
End Sub
' yöntem
Public Function m2(...)
....
End Function
End Class
Yukarıdaki C1 sınıfından yola çıkarak, çok sayıda O1, O2,… nesnesi oluşturulabilir. Hepsi p1, p2,… özelliklerine ve m3, m4,… yöntemlerine sahip olacaktır. Ancak pi özellikleri için farklı değerlere sahip olacaklardır ve böylece her biri kendine özgü bir duruma sahip olacaktır. Benzer şekilde, şu bildirim:
ifadesi, Integer türünde (sınıfında) iki nesne (burada bu terim yanlış kullanılmıştır) oluşturur. Bu nesnelerin tek özelliği, değerleridir. O1, C1 türünde bir nesne ise, O1.p1, O1'in p1 özelliğini, O1.m1 ise O1 sınıfının m1 yöntemini ifade eder. İlk nesne modelini ele alalım: personne sınıfı.
3.1.2. Kişi sınıfının tanımı
personne sınıfının tanımı şu şekilde olacaktır:
Public Class personne
' öznitelikler
Private prenom As String
Private nom As String
Private age As Integer
' yöntem
Public Sub initialise(ByVal P As String, ByVal N As String, ByVal age As Integer)
Me.prenom = P
Me.nom = N
Me.age = age
End Sub
' yöntem
Public Sub identifie()
Console.Out.WriteLine((prenom & "," & nom & "," & age))
End Sub
End Class
Burada bir sınıfın, yani bir veri türünün tanımını görüyoruz. Bu türden değişkenler oluşturduğumuzda, bunlara nesneler veya sınıf örnekleri adını vereceğiz. Dolayısıyla bir sınıf, nesnelerin oluşturulduğu bir kalıptır. Bir sınıfın üyeleri veya alanları veriler (öznitelikler), yöntemler (fonksiyonlar) veya özellikler olabilir. Özellikler, nesnenin özniteliklerinin değerini öğrenmek veya belirlemek için kullanılan özel yöntemlerdir. Bu alanlar, aşağıdaki üç anahtar kelimeden biriyle birlikte kullanılabilir:
Özel (private) bir alana yalnızca sınıfın kendi iç yöntemleri erişebilir | |
Genel (public) bir alana, sınıf içinde tanımlanmış olsun ya da olmasın tüm işlevler tarafından erişilebilir | |
Korunan (protected) bir alana yalnızca sınıfın veya türetilmiş bir nesnenin (daha sonra miras kavramına bakınız) dahili yöntemleri tarafından erişilebilir. |
Genel olarak, bir sınıfın verileri özel olarak bildirilirken, yöntemleri ve özellikleri genel olarak bildirilir. Bu, bir nesnenin kullanıcısının (programcı)
- nesnenin özel verilerine doğrudan erişemez
- nesnenin genel yöntemlerini ve özellikle de özel verilerine erişim sağlayan yöntemleri kullanabilir.
Bir sınıfın bildirim sözdizimi şöyledir:
public class classe
private donnée ou méthode ou propriété privée
public donnée ou méthode ou propriété publique
protected donnée ou méthode ou propriété protégée
end class
private, protected ve public özniteliklerinin bildirilme sırası herhangi bir kural gerektirmez.
3.1.3. Yöntem,
Şu şekilde tanımlanan [personne] sınıfımıza geri dönelim:
Public Class personne
' özellikler
Private prenom As String
Private nom As String
Private age As Integer
' yöntem
Public Sub initialise(ByVal P As String, ByVal N As String, ByVal age As Integer)
Me.prenom = P
Me.nom = N
Me.age = age
End Sub
' yöntem
Public Sub identifie()
Console.Out.WriteLine((prenom & "," & nom & "," & age))
End Sub
End Class
initialise yönteminin rolü nedir? nom, prenom ve age, personne sınıfının özel verileri olduğundan, şu komutlar:
yazıları geçersizdir. personne türünde bir nesneyi genel bir yöntem aracılığıyla başlatmamız gerekir. Bu, initialise yönteminin görevidir. Şöyle yazacağız:
p1.initialise yazımı, initialise'in erişimi herkese açık olduğu için geçerlidir.
3.1.4. new operatörü
Komut dizisi
hatalıdır.
komutu, p1'i personne türünde bir nesneye referans olarak tanımlamaktadır. Bu nesne henüz mevcut değildir ve bu nedenle p1 başlatılmamıştır. Bu, sanki şunu yazmış gibi bir durumdur:
burada nothing anahtar sözcüğüyle, p1 değişkeninin henüz hiçbir nesneye referans vermediğini açıkça belirtmiş oluruz. Daha sonra şunu yazdığımızda
yazdığımızda, p1 tarafından referans verilen nesnenin initialise yöntemini çağırmış oluruz. Ancak bu nesne henüz mevcut değildir ve derleyici bir hata bildirir. p1'in bir nesneye referans vermesi için şunu yazmak gerekir:
Bu, henüz başlatılmamış bir personne türü nesne oluşturur: nom ve prenom öznitelikleri, String türündeki nesnelere referanslar olduğundan nothing değerini alacak, ve age ise 0 değerini alacaktır. Dolayısıyla varsayılan bir başlatma söz konusudur. Artık p1 bir nesneye referans verdiğine göre, bu nesnenin başlatma komutu
geçerlidir.
3.1.5. Me anahtar sözcüğü
initialise yönteminin koduna bakalım:
Public Sub initialise(ByVal P As String, ByVal N As String, ByVal age As Integer)
Me.prenom = P
Me.nom = N
Me.age = age
End Sub
Me.prenom=P komutu, geçerli nesnenin (Me) prenom özniteliğine P değerinin atandığını ifade eder. Me anahtar sözcüğü, geçerli nesneyi belirtir: yani, yürütülen yöntemin bulunduğu nesneyi. Bunu nasıl anlarız? Çağıran programda p1 tarafından referans verilen nesnenin nasıl başlatıldığını inceleyelim:
p1 nesnesinin initialise yöntemi çağrılmaktadır. Bu yöntemde Me nesnesine atıfta bulunulduğunda, aslında p1 nesnesine atıfta bulunulmaktadır. initialise yöntemi şu şekilde de yazılabilirdi:
Public Sub initialise(ByVal P As String, ByVal N As String, ByVal age As Integer)
prenom = P
nom = N
Me.age = age
End Sub
Bir nesnenin yöntemi, bu nesnenin A özniteliğine başvurduğunda, Me.A yazımı örtük olarak kullanılır. Tanımlayıcı çakışması olduğunda ise bu yazım açıkça kullanılmalıdır. Aşağıdaki komutda durum böyledir:
Me.age=age;
burada age, hem geçerli nesnenin bir özniteliğini hem de yöntem tarafından alınan age parametresini ifade eder. Bu durumda, age özniteliğini Me.age olarak belirtmek suretiyle belirsizliği gidermek gerekir.
3.1.6. Bir test programı
İşte kısa bir test programı:
Public Class personne
' özellikler
Private prenom As String
Private nom As String
Private age As Integer
' yöntem
Public Sub initialise(ByVal P As String, ByVal N As String, ByVal age As Integer)
Me.prenom = P
Me.nom = N
Me.age = age
End Sub
' yöntem
Public Sub identifie()
Console.Out.WriteLine((prenom & "," & nom & "," & age))
End Sub
End Class
ve elde edilen sonuçlar:
dos>vbc personne1.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
3.1.7. Derlenmiş sınıf dosyası (assembly) kullanma
Önceki örnekte, test programımızda iki sınıf olduğu dikkatinizi çekecektir: personne ve test1 sınıfları. Bunu yapmanın başka bir yolu daha vardır:
-
"person" sınıfını, "assembly" adı verilen özel bir dosyaya derleriz. Bu dosyanın uzantısı .dll'dir
-
"person" sınıfını içeren derlemeyi referans alarak "test1" sınıfını derleriz.
İki kaynak dosyası şu şekilde olur:
test.vb | |
personne2.vb | |
personne sınıfı aşağıdaki komutla derlenir:
dos>vbc /t:library personne2.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
dos>dir
24/02/2004 16:50 509 personne2.vb
24/02/2004 16:49 143 test.vb
24/02/2004 16:50 3 584 personne2.dll
Derleme sonucunda personne2.dll dosyası oluşturuldu. "Assembly" dosyası oluşturulmasını belirten derleme seçeneği /t:library'tir. Şimdi test.vb dosyasını derleyelim:
dos>vbc /r:personne2.dll test.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
dos>dir
24/02/2004 16:50 509 personne2.vb
24/02/2004 16:49 143 test.vb
24/02/2004 16:50 3 584 personne2.dll
24/02/2004 16:51 3 072 test.exe
/r:personne2.dll derleme seçeneği, derleyiciye personne2.dll dosyasında belirli sınıfları bulacağını bildirir. test.vb kaynak dosyasında, test.vb kaynak dosyasında tanımlanmamış olan personne sınıfına bir referans bulduğunda, /r seçeneği tarafından referans verilen .dll dosyalarında personne sınıfını arayacaktır. Burada, personne2.dll derlemesinde personne sınıfını bulacaktır. Bu derlemeye başka sınıflar da eklenebilirdi. Derleme sırasında birden fazla derlenmiş sınıf dosyası kullanmak için şu şekilde yazılır:
test1.exe programının çalıştırılması şu sonuçları verir:
3.1.8. Başka bir yöntem başlatır
Yine personne sınıfını ele alalım ve ona aşağıdaki yöntemi ekleyelim:
' yöntem
Public Sub initialise(ByVal P As personne)
prenom = P.prenom
nom = P.nom
Me.age = P.age
End Sub
Artık initialise adında iki yöntemimiz var: farklı parametreler kabul ettikleri sürece bu durum geçerlidir. Burada da durum böyledir. Parametre artık bir kişiye ait P referansıdır. P kişisinin öznitelikleri, bu durumda geçerli nesneye (Me) atanır. initialise yönteminin, P nesnesinin özniteliklerine doğrudan erişimi olduğu, ancak bu özniteliklerin private türünde olduğu dikkatinizi çekecektir. Bu her zaman geçerlidir: C sınıfına ait bir O1 nesnesi, her zaman aynı C sınıfına ait nesnelerin özniteliklerine erişebilir. İşte yeni personne sınıfının bir testi; bu sınıf, daha önce açıklandığı gibi personne.dll içinde derlenmiştir:
' seçenekler
Option Explicit On
Option Strict On
' ad alanları
Imports System
Module test1
Sub Main()
Dim p1 As New personne
p1.initialise("Jean", "Dupont", 30)
Console.Out.Write("p1=")
p1.identifie()
Dim p2 As New personne
p2.initialise(p1)
Console.Out.Write("p2=")
p2.identifie()
End Sub
End Module
ve sonuçları:
3.1.9. Person sınıfının oluşturucuları
Oluşturucu, New adını taşıyan ve nesnenin oluşturulması sırasında çağrılan bir yordamdır. Genellikle nesneyi başlatmak için kullanılır. Bir sınıfın n argüman kabul eden bir oluşturucusu varsa argi, bu sınıfa ait bir nesnenin bildirilmesi ve başlatılması şu şekilde yapılabilir:
dim objet as classe =new classe(arg1,arg2, ... argn)
veya
dim objet as classe
…
objet=new classe(arg1,arg2, ... argn)
Bir sınıfın bir veya daha fazla yapıcı işlevi varsa, bu sınıftan bir nesne oluşturmak için bu yapıcı işlevlerden birinin kullanılması zorunludur. C sınıfının hiçbir yapıcı işlevi yoksa, varsayılan olarak parametresiz yapıcı işlevi olan public New() kullanılır. Bu durumda nesnenin özellikleri varsayılan değerlerle başlatılır. Önceki programlarda da böyle olmuştu; orada şunu yazmıştık:
personne sınıfımıza iki yapıcı oluşturalım:
' seçenekler
Option Explicit On
Option Strict On
' ad alanları
Imports System
' kişi sınıfı
Public Class personne
' özellikler
Private prenom As String
Private nom As String
Private age As Integer
' oluşturucular
Public Sub New(ByVal P As [String], ByVal N As [String], ByVal age As Integer)
initialise(P, N, age)
End Sub
Public Sub New(ByVal P As personne)
initialise(P)
End Sub
' nesne başlatma yöntemleri
Public Sub initialise(ByVal P As String, ByVal N As String, ByVal age As Integer)
Me.prenom = P
Me.nom = N
Me.age = age
End Sub
Public Sub initialise(ByVal P As personne)
prenom = P.prenom
nom = P.nom
Me.age = P.age
End Sub
' yöntem
Public Sub identifie()
Console.Out.WriteLine((prenom & "," & nom & "," & age))
End Sub
End Class
Her iki yapıcı da sadece karşılık gelen initialise yöntemlerini çağırır. Hatırlatmak gerekirse, bir yapıcıda örneğin initialise(P) notasyonu bulunduğunda, derleyici bunu Me.initialise(P) olarak çevirir. Dolayısıyla, oluşturucuda initialise yöntemi, Me tarafından referans verilen nesne, yani o anda oluşturulmakta olan nesne üzerinde işlem yapmak üzere çağrılır. İşte kısa bir test programı:
' seçenekler
Option Explicit On
Option Strict On
' ad alanları
Imports System
' test sayfası
Module test
Sub Main()
Dim p1 As New personne("Jean", "Dupont", 30)
Console.Out.Write("p1=")
p1.identifie()
Dim p2 As New personne(p1)
Console.Out.Write("p2=")
p2.identifie()
End Sub
End Module
ve elde edilen sonuçlar:
3.1.10. Nesne referansları
Her zaman aynı personne sınıfını kullanıyoruz. Test programı şu şekilde olur:
' seçenekler
Option Explicit On
Option Strict On
' ad alanları
Imports System
' test sayfası
Module test
Sub Main()
' p1
Dim p1 As New personne("Jean", "Dupont", 30)
Console.Out.Write("p1=")
p1.identifie()
' p2, p1 ile aynı nesneye başvurur
Dim p2 As personne = p1
Console.Out.Write("p2=")
p2.identifie()
' p3, p1 tarafından referans verilen nesnenin bir kopyası olacak bir nesneye referans verir
Dim p3 As New personne(p1)
Console.Out.Write("p3=")
p3.identifie()
' p1 tarafından referans verilen nesnenin durumu değiştirilir
p1.initialise("Micheline", "Benoît", 67)
Console.Out.Write("p1=")
p1.identifie()
' p2=p1 olduğu için, p2'nin işaret ettiği nesnenin durumu değişmiş olmalıdır
Console.Out.Write("p2=")
p2.identifie()
' p3, p1 ile aynı nesneye referans vermediğinden, p3 tarafından referans verilen nesnenin durumu değişmemiş olmalıdır
Console.Out.Write("p3=")
p3.identifie()
End Sub
End Module
Elde edilen sonuçlar şunlardır:
p1=Jean,Dupont,30
p2=Jean,Dupont,30
p3=Jean,Dupont,30
p1=Micheline,Benoît,67
p2=Micheline,Benoît,67
p3=Jean,Dupont,30
p1 değişkeni şu şekilde tanımlandığında
p1, personne("Jean","Dupont",30) nesnesine başvurur, ancak nesnenin kendisi değildir. C dilinde buna bir işaretçi denir; c.a.d, oluşturulan nesnenin adresidir. Ardından şunu yazarsak:
Değiştirilen personne("Jean","Dupont",30) nesnesi değil, değeri değişen p1 referansıdır. personne("Jean","Dupont",30) nesnesi, başka hiçbir değişken tarafından referanslanmıyorsa "kaybolur".
Şu kod yazıldığında:
yazıldığında, p2 işaretçisi başlatılır: bu işaretçi, p1 işaretçisiyle aynı nesneye "işaret eder" (aynı nesneyi gösterir). Dolayısıyla, p1 tarafından "işaret edilen" (veya referans verilen) nesne değiştirilirse, p2 tarafından referans verilen nesne de değiştirilmiş olur.
Şu kod yazıldığında:
yazıldığında, p1 tarafından referans verilen nesnenin bir kopyası olan yeni bir nesne oluşturulur. Bu yeni nesne, p3 tarafından referans verilecektir. p1 tarafından "işaret edilen" (veya referans verilen) nesne değiştirilirse, p3 tarafından referans verilen nesne hiçbir şekilde değiştirilmez. Elde edilen sonuçlar da bunu göstermektedir.
3.1.11. Geçici nesneler
Bir ifadede, bir nesnenin oluşturucusuna açıkça başvurulabilir: nesne oluşturulur, ancak ona erişimimiz yoktur (örneğin, onu değiştirmek için). Bu geçici nesne, ifadenin değerlendirilmesi için oluşturulur ve ardından terk edilir. İşgal ettiği bellek alanı, daha sonra "çöp toplayıcı" adı verilen bir program tarafından otomatik olarak geri kazanılacaktır; bu programın görevi, program verileri tarafından artık referans gösterilmeyen nesnelerin işgal ettiği bellek alanını geri kazanmaktır. Aşağıdaki yeni test programını ele alalım:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
' test sayfası
Module test
Sub Main()
Dim p As New personne(New personne("Jean", "Dupont", 30))
p.identifie()
End Sub
End Module
ve personne sınıfının oluşturucularını bir mesaj görüntüleyecek şekilde değiştirelim:
' yapıcılar
Public Sub New(ByVal P As [String], ByVal N As [String], ByVal age As Integer)
Console.Out.WriteLine("Constructeur personne(String, String, integer)")
initialise(P, N, age)
End Sub
Public Sub New(ByVal P As personne)
Console.Out.WriteLine("Constructeur personne(personne)")
initialise(P)
End Sub
Şu sonuçları elde ediyoruz:
dos>test
Constructeur personne(String, String, integer)
Constructeur personne(personne)
Jean,Dupont,30
Bu, iki geçici nesnenin sırayla oluşturulduğunu göstermektedir.
3.1.12. Özel özniteliklerin okunması ve yazılması için yöntemler
personne sınıfına, nesnelerin özniteliklerinin durumunu okumak veya değiştirmek için gerekli yöntemleri ekliyoruz:
Imports System
Public Class personne
' özellikler
Private prenom As [String]
Private nom As [String]
Private age As Integer
' oluşturucular
Public Sub New(ByVal P As [String], ByVal N As [String], ByVal age As Integer)
Me.prenom = P
Me.nom = N
Me.age = age
End Sub
Public Sub New(ByVal P As personne)
Me.prenom = P.prenom
Me.nom = P.nom
Me.age = P.age
End Sub
' tanımlayıcılar
Public Sub identifie()
Console.Out.WriteLine((prenom + "," + nom + "," + age))
End Sub
' erişim yöntemleri
Public Function getPrenom() As [String]
Return prenom
End Function
Public Function getNom() As [String]
Return nom
End Function
Public Function getAge() As Integer
Return age
End Function
'değiştiriciler
Public Sub setPrenom(ByVal P As [String])
Me.prenom = P
End Sub
Public Sub setNom(ByVal N As [String])
Me.nom = N
End Sub
Public Sub setAge(ByVal age As Integer)
Me.age = age
End Sub
End Class
Yeni sınıfı aşağıdaki programla test ediyoruz:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
' test sayfası
Public Module test
Sub Main()
Dim P As New personne("Jean", "Michelin", 34)
Console.Out.WriteLine(("P=(" & P.getPrenom() & "," & P.getNom() & "," & P.getAge() & ")"))
P.setAge(56)
Console.Out.WriteLine(("P=(" & P.getPrenom() & "," & P.getNom() & "," & P.getAge() & ")"))
End Sub
End Module
ve şu sonuçları elde ediyoruz:
3.1.13. Özellikler
Bir sınıfın özniteliklerine erişmenin başka bir yolu da özellikler oluşturmaktır. Bu özellikler, özel öznitelikleri sanki genelmiş gibi işlememize olanak tanır. Aşağıdaki personne sınıfını ele alalım; burada önceki erişim ve değiştirme yöntemleri, okuma ve yazma özellikleriyle değiştirilmiştir:
' seçenekler
Option Explicit On
Option Strict On
' ad alanları
Imports System
' kişi sınıfı
Public Class personne
' özellikler
Private _prenom As [String]
Private _nom As [String]
Private _age As Integer
' üreticiler
Public Sub New(ByVal P As [String], ByVal N As [String], ByVal age As Integer)
Me._prenom = P
Me._nom = N
Me._age = age
End Sub
Public Sub New(ByVal P As personne)
Me._prenom = P._prenom
Me._nom = P._nom
Me._age = P._age
End Sub
' tanımlar
Public Sub identifie()
Console.Out.WriteLine((_prenom & "," & _nom & "," & _age))
End Sub
' özellikler
Public Property prenom() As String
Get
Return _prenom
End Get
Set(ByVal Value As String)
_prenom = Value
End Set
End Property
Public Property nom() As String
Get
Return _nom
End Get
Set(ByVal Value As String)
_nom = Value
End Set
End Property
Public Property age() As Integer
Get
Return _age
End Get
Set(ByVal Value As Integer)
' yaş geçerli mi?
If Value >= 0 Then
_age = Value
Else
Throw New Exception("âge (" & Value & ") invalide")
End If
End Set
End Property
End Class
Bir Property özelliği, bir özniteliğin değerini okumaya (get) veya ayarlamaya (set) olanak tanır. Örneğimizde, özelliklerin temel özniteliklerin adlarını taşıması için öznitelik adlarının başına _ ön eki ekledik. Zira bir özellik, yönettiği özniteliğin adıyla aynı adı taşıyamaz; aksi takdirde sınıfta ad çakışması meydana gelir. Bu nedenle özniteliklerimize _prenom, _nom, _age adlarını verdik ve yapıcıları ile yöntemleri buna göre değiştirdik. Ardından nom, prenom ve age adlı üç özellik oluşturduk. Bir özellik şu şekilde tanımlanır:
Public Property nom() As Type
Get
...
End Get
Set(ByVal Value As Type)
...
End Set
End Property
burada Type, özellik tarafından yönetilen özniteliğin türü olmalıdır. Bu özellik, get ve set adlı iki yönteme sahip olabilir. Get yöntemi genellikle yönettiği özniteliğin değerini döndürmekle görevlidir (başka bir şey de döndürebilir, bunu engelleyen bir şey yoktur). set yöntemi, value adlı bir parametre alır ve bunu normalde yönettiği özniteliğe atar. Bu yöntem, alınan değerin geçerliliğini kontrol etmek için bu fırsatı değerlendirebilir ve değer geçersiz çıkarsa bir istisna oluşturabilir. Burada yaş için yapılan da budur.
Bu get ve set yöntemleri nasıl çağrılır? Aşağıdaki test programını ele alalım:
' seçenekler
Option Explicit On
Option Strict On
' ad alanları
Imports System
' test sayfası
Module test
Sub Main()
Dim P As New personne("Jean", "Michelin", 34)
Console.Out.WriteLine(("P=(" & P.prenom & "," & P.nom & "," & P.age & ")"))
P.age = 56
Console.Out.WriteLine(("P=(" & P.prenom & "," & P.nom & "," & P.age & ")"))
Try
P.age = -4
Catch ex As Exception
Console.Error.WriteLine(ex.Message)
End Try
End Sub
End Module
Şu komutta
komutunda, P kişisinin prenom, nom ve age özelliklerinin değerleri alınmaya çalışılır. Bu durumda, bu özelliklerin get yöntemi çağrılır ve bu yöntem, yönettikleri özniteliğin değerini döndürür.
Aşağıdaki komutta
komutunda, age özelliğinin değeri ayarlanmak istenmektedir. Bu durumda, bu özelliğin set yöntemi çağrılır. Bu yöntem, value parametresinde 56 değerini alır.
C sınıfına ait ve yalnızca get yöntemini tanımlayan bir P özelliği, salt okunur olarak adlandırılır. c, C sınıfına ait bir nesne ise, c.P=değer işlemi derleyici tarafından reddedilir.
Önceki test programının çalıştırılması şu sonuçları verir:
Dolayısıyla özellikler, özel öznitelikleri sanki genelmiş gibi işlememize olanak tanır.
3.1.14. Sınıf yöntemleri ve öznitelikleri
Bir uygulamada oluşturulan [personne] nesnelerinin sayısını saymak istediğimizi varsayalım. Bir sayacı kendimiz yönetebiliriz, ancak burada veya orada oluşturulan geçici nesneleri unutma riski vardır. [personne] sınıfının oluşturucularına, bir sayacı artıran bir komut eklemek daha güvenli görünür. Sorun, oluşturucunun sayacı artırabilmesi için bu sayaca bir referans aktarılmasıdır: onlara yeni bir parametre aktarılması gerekir. Sayacı sınıf tanımına da dahil edebiliriz. Bu, sınıfın kendisinin bir özniteliği olduğu ve bu sınıfa ait belirli bir nesnenin özniteliği olmadığı için, Shared anahtar sözcüğüyle farklı şekilde tanımlanır:
Buna başvurmak için, personne._nbPersonnes yazarak bunun personne sınıfının kendisinin bir özniteliği olduğunu gösteririz. Burada, sınıfın dışından doğrudan erişilemeyen özel bir öznitelik oluşturduk. Bu nedenle, nbPersonnes sınıf özniteliğine erişim sağlamak için bir genel özellik oluşturuyoruz. nbPersonnes değerini almak için, bu özelliğin get yönteminin belirli bir personne nesnesine ihtiyacı yoktur: çünkü _nbPersonnes belirli bir nesnenin özniteliği değil, tüm sınıfın özniteliğidir. Bu nedenle, yine Shared olarak tanımlanmış bir özelliğe ihtiyaç vardır:
Bu, dışarıdan personne.nbPersonnes sözdizimiyle çağrılacaktır. Özellik, set yöntemi sunmadığı için salt okunur olarak tanımlanmıştır (ReadOnly). İşte bir örnek. personne sınıfı şu şekilde olur:
Option Explicit On
Option Strict On
' ad alanları
Imports System
' sınıf
Public Class personne
' sınıf öznitelikleri
Private Shared _nbPersonnes As Long = 0
' örnek öznitelikleri
Private _prenom As [String]
Private _nom As [String]
Private _age As Integer
' yapıcılar
Public Sub New(ByVal P As [String], ByVal N As [String], ByVal age As Integer)
' bir kişi daha
_nbPersonnes += 1
Me._prenom = P
Me._nom = N
Me._age = age
End Sub
Public Sub New(ByVal P As personne)
' bir kişi daha
_nbPersonnes += 1
Me._prenom = P._prenom
Me._nom = P._nom
Me._age = P._age
End Sub
' tanımlar
Public Sub identifie()
Console.Out.WriteLine((_prenom & "," & _nom & "," & _age))
End Sub
' sınıf özelliği
Public Shared ReadOnly Property nbPersonnes() As Long
Get
Return _nbPersonnes
End Get
End Property
' örnek özellikleri
Public Property prenom() As String
Get
Return _prenom
End Get
Set(ByVal Value As String)
_prenom = Value
End Set
End Property
Public Property nom() As String
Get
Return _nom
End Get
Set(ByVal Value As String)
_nom = Value
End Set
End Property
Public Property age() As Integer
Get
Return _age
End Get
Set(ByVal Value As Integer)
' yaş geçerli mi?
If Value >= 0 Then
_age = Value
Else
Throw New Exception("âge (" & Value & ") invalide")
End If
End Set
End Property
End Class
Aşağıdaki programla:
' seçenekler
Option Explicit On
Option Strict On
' ad alanları
Imports System
' test pg'si
Module test
Sub Main()
Dim p1 As New personne("Jean", "Dupont", 30)
Dim p2 As New personne(p1)
Console.Out.WriteLine(("Nombre de personnes créées : " & personne.nbPersonnes))
End Sub
End Module
şu sonuçlar elde edilir:
3.1.15. Bir nesnenin bir fonksiyona aktarılması
Daha önce de belirttiğimiz gibi, varsayılan olarak VB.NET, bir fonksiyonun etkin parametrelerini değer olarak aktarır: etkin parametrelerin değerleri, biçimsel parametrelere kopyalanır. Bir nesne söz konusu olduğunda, nesne referansı yerine sistematik olarak nesne denilmesinden kaynaklanan dil kullanımındaki yanlışlığa aldanmamak gerekir. Bir nesne, yalnızca o nesneye ait bir referans (işaretçi) aracılığıyla işlenir. Dolayısıyla bir fonksiyona aktarılan, nesnenin kendisi değil, o nesneye ait bir referanstır. Bu nedenle, biçimsel parametreye kopyalanan nesnenin kendisinin değeri değil, referansın değeridir: yeni bir nesne oluşturulmaz. R1 nesne referansı bir fonksiyona aktarılırsa, bu referans karşılık gelen biçimsel parametreye (R2) kopyalanır. Dolayısıyla, R2 ve R1 referansları aynı nesneyi işaret eder. İşlev, R2 tarafından işaret edilen nesneyi değiştirirse, R1 tarafından referans verilen nesneyi de değiştirir; çünkü ikisi aynıdır.
![]() |
Aşağıdaki örnek bunu göstermektedir:
' seçenekler
Option Explicit On
Option Strict On
' ad alanları
Imports System
' test sayfası
Module test
Sub Main()
' bir kişi p1
Dim p1 As New personne("Jean", "Dupont", 30)
' görüntüleme p1
Console.Out.Write("Paramètre effectif avant modification : ")
p1.identifie()
' p1'in düzenlenmesi
modifie(p1)
' p1 görüntüleme
Console.Out.Write("Paramètre effectif après modification : ")
p1.identifie()
End Sub
Sub modifie(ByVal P As personne)
' kişi P görüntüleme
Console.Out.Write("Paramètre formel avant modification : ")
P.identifie()
' P düzenleme
P.prenom = "Sylvie"
P.nom = "Vartan"
P.age = 52
' P görüntüleme
Console.Out.Write("Paramètre formel après modification : ")
P.identifie()
End Sub
End Module
Elde edilen sonuçlar şunlardır:
Paramètre effectif avant modification : Jean,Dupont,30
Paramètre formel avant modification : Jean,Dupont,30
Paramètre formel après modification : Sylvie,Vartan,52
Paramètre effectif après modification : Sylvie,Vartan,52
Görüldüğü üzere, yalnızca bir nesne oluşturulmuştur: Main prosedürüne ait p1 nesnesi; ve bu nesne, modifie işlevi tarafından değiştirilmiştir.
3.1.16. Kişi tablosu
Bir nesne, diğer veriler gibi bir veridir ve bu nedenle birden fazla nesne bir dizide bir araya getirilebilir:
' seçenekler
Option Explicit On
Option Strict On
' ad alanları
Imports System
' test sayfası
Module test
Sub Main()
' kişi tablosu
Dim amis(2) As personne
amis(0) = New personne("Jean", "Dupont", 30)
amis(1) = New personne("Sylvie", "Vartan", 52)
amis(2) = New personne("Neil", "Armstrong", 66)
' görüntüleme
Console.Out.WriteLine("----------------")
Dim i As Integer
For i = 0 To amis.Length - 1
amis(i).identifie()
Next i
End Sub
End Module
Dim amis(2) As personne komutu, personne türünde 3 elemanlı bir dizi oluşturur. Bu 3 eleman burada nothing ve c.a.d değerleriyle başlatılır; bu değerler herhangi bir nesneye referans vermez. Yine, dilin yanlış kullanımı nedeniyle, nesne dizisinden söz ediliyor; oysa bu sadece nesne referanslarından oluşan bir dizidir. Kendisi de bir nesne olan nesne dizisinin oluşturulması, elemanlarının türünde hiçbir nesne oluşturmaz: bunu daha sonra yapmak gerekir. Aşağıdaki sonuçlar elde edilir:
3.2. Örnekle Kalıtım
3.2.1. Genel Bilgiler
Burada miras kavramını ele alıyoruz. Mirasın amacı, mevcut bir sınıfı ihtiyaçlarımıza uygun hale getirmek için "kişiselleştirmektir". enseignant sınıfını oluşturmak istediğimizi varsayalım: bir öğretmen, özel bir kişidir. Başka bir kişinin sahip olmayacağı özellikleri vardır: örneğin, öğrettiği ders. Ancak aynı zamanda her insanın sahip olduğu özelliklere de sahiptir: adı, soyadı ve yaşı. Dolayısıyla bir öğretmen, personne sınıfının tam bir parçasıdır, ancak ek özelliklere de sahiptir. enseignant sınıfını sıfırdan yazmak yerine, personne sınıfının mevcut özelliklerini alıp bunları öğretmenlerin kendine özgü özelliklerine uyarlamayı tercih ederiz. Bunu mümkün kılan şey, miras alma kavramıdır. enseignant sınıfının personne sınıfının özelliklerini miras aldığını ifade etmek için şunu yazacağız:
Public Class enseignant
Inherits personne
İki satırlık bu özel sözdizimine dikkat edilmelidir. personne sınıfına üst sınıf (veya ana sınıf), enseignant sınıfına ise türetilmiş sınıf (veya alt sınıf) denir. Bir enseignant nesnesi, bir personne nesnesinin tüm özelliklerine sahiptir: aynı özniteliklere ve yöntemlere sahiptir. Ana sınıfın bu öznitelikleri ve yöntemleri, alt sınıfın tanımında tekrarlanmaz; sadece alt sınıf tarafından eklenen öznitelikler ve yöntemler belirtilir. personne sınıfının şu şekilde tanımlandığını varsayalım:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
' kişi sınıfı
Public Class personne
' sınıf öznitelikleri
Private Shared _nbPersonnes As Long = 0
' örnek öznitelikleri
Private _prenom As [String]
Private _nom As [String]
Private _age As Integer
' oluşturucular
Public Sub New(ByVal P As [String], ByVal N As [String], ByVal age As Integer)
' bir kişi daha
_nbPersonnes += 1
' oluşturma
Me._prenom = P
Me._nom = N
Me._age = age
' izleme
Console.Out.WriteLine("Construction personne(string, string, int)")
End Sub
Public Sub New(ByVal P As personne)
' bir kişi daha
_nbPersonnes += 1
' inşaat
Me._prenom = P._prenom
Me._nom = P._nom
Me._age = P._age
' takip
Console.Out.WriteLine("Construction personne(string, string, int)")
End Sub
' sınıf özelliği
Public Shared ReadOnly Property nbPersonnes() As Long
Get
Return _nbPersonnes
End Get
End Property
' örnek özellikleri
Public Property prenom() As String
Get
Return _prenom
End Get
Set(ByVal Value As String)
_prenom = Value
End Set
End Property
Public Property nom() As String
Get
Return _nom
End Get
Set(ByVal Value As String)
_nom = Value
End Set
End Property
Public Property age() As Integer
Get
Return _age
End Get
Set(ByVal Value As Integer)
' yaş geçerli mi?
If Value >= 0 Then
_age = Value
Else
Throw New Exception("âge (" & Value & ") invalide")
End If
End Set
End Property
Public ReadOnly Property identite() As String
Get
Return "personne(" & _prenom & "," & _nom & "," & age & ")"
End Get
End Property
End Class
identifie yöntemi, kişiyi tanımlayan ve salt okunur olan identité özelliği ile değiştirilmiştir. personne sınıfından miras alan bir enseignant sınıfı oluşturuyoruz:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
Public Class enseignant
Inherits personne
' özellikler
Private _section As Integer
' oluşturucu
Public Sub New(ByVal P As String, ByVal N As String, ByVal age As Integer, ByVal section As Integer)
MyBase.New(P, N, age)
Me._section = section
' izleme
Console.Out.WriteLine("Construction enseignant(string,string,int,int)")
End Sub
' bölüm özelliği
Public Property section() As Integer
Get
Return _section
End Get
Set(ByVal Value As Integer)
_section = Value
End Set
End Property
End Class
enseignant sınıfı, personne sınıfının yöntemlerine ve özniteliklerine şunları ekler:
- section özniteliği; bu, öğretmenin öğretmen kadrosu içinde ait olduğu bölüm numarasıdır (genel olarak her ders dalı için bir bölüm)
- bir öğretmenin tüm özniteliklerini sıfırlamaya olanak tanıyan yeni bir oluşturucu
Bildirim
Public Class enseignant
Inherits personne
, enseignant sınıfının personne sınıfından türediğini belirtir.
3.2.2. Öğretmen nesnesinin oluşturulması
enseignant sınıfının oluşturucusu şöyledir:
' oluşturucu
Public Sub New(ByVal P As String, ByVal N As String, ByVal age As Integer, ByVal section As Integer)
MyBase.New(P, N, age)
Me._section = section
' takip
Console.Out.WriteLine("Construction enseignant(string,string,int,int)")
End Sub
Beyanname
Public Sub New(ByVal P As String, ByVal N As String, ByVal age As Integer, ByVal section As Integer)
, yapıcının dört parametre aldığını belirtir: P, N, age, section. Bu yapıcı, üç parametreyi ((P,N,age)) temel sınıfına, yani buradaki personne sınıfına aktarmalıdır. Bu sınıfın, aktarılan parametrelerle ((P,N,age)) bir kişi nesnesi oluşturmaya olanak tanıyan personne(string, string, int) adlı bir yapıcıya sahip olduğu bilinmektedir. [enseignant] sınıfı, (P, N, yaş) parametrelerini temel sınıfına şu şekilde aktarır:
MyBase.New(P, N, age)
Temel sınıfın oluşturulması tamamlandıktan sonra, enseignant nesnesinin oluşturulması, oluşturucunun gövdesinin yürütülmesiyle devam eder:
Me._section = section
Özetle, türetilmiş bir sınıfın oluşturucusu:
- oluşturulması için gerekli parametreleri temel sınıfa aktarır
- diğer parametreleri, kendisine özgü öznitelikleri başlatmak için kullanır
Şu şekilde yazmak da tercih edilebilirdi:
Public Sub New(ByVal P As String, ByVal N As String, ByVal age As Integer, ByVal section As Integer)
Me._prenom = P
Me._nom = N
Me._age = age
Me._section = section
' takip
Console.Out.WriteLine("Construction enseignant(string,string,int,int)")
End Sub
Bu imkansız. personne sınıfı, _prenom, _nom ve _age adlı üç alanını özel (private) olarak tanımlamıştır. Yalnızca aynı sınıfa ait nesneler bu alanlara doğrudan erişebilir. Buradaki gibi alt nesneler de dahil olmak üzere diğer tüm nesneler, bu alanlara erişmek için genel yöntemleri kullanmak zorundadır. personne sınıfı bu üç alanı korumalı (protected) olarak tanımlamış olsaydı durum farklı olurdu: bu durumda, türetilmiş sınıfların bu üç alana doğrudan erişmesine izin vermiş olurdu. Örneğimizde, üst sınıfın oluşturucusunu kullanmak doğru çözümdü ve bu genel olarak uygulanan yöntemdir: bir alt sınıf nesnesi oluşturulurken, önce üst sınıf nesnesinin oluşturucusu çağrılır, ardından bu sefer alt sınıf nesnesine (örneğimizde section) özgü başlatma işlemleri tamamlanır.
personne ve enseignant sınıflarını derlemelere derleyelim:
dos>vbc /t:library personne.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
dos>vbc /r:personne.dll /t:library enseignant.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
dos>dir
25/02/2004 10:08 1 828 personne.vb
25/02/2004 10:11 675 enseignant.vb
25/02/2004 10:12 223 test.vb
25/02/2004 10:16 4 096 personne.dll
25/02/2004 10:16 3 584 enseignant.dll
enseignant alt sınıfını derlemek için, personne sınıfını içeren personne.dll dosyasına referans verilmesi gerektiği dikkatinizi çekecektir. İlk test programımızı deneyelim:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
Module test
Sub Main()
Console.Out.WriteLine(New enseignant("Jean", "Dupont", 30, 27).identite)
End Sub
End Module
Bu program, yalnızca bir enseignant nesnesi (new) oluşturup onu tanımlamakla yetinir. enseignant sınıfında identité adlı bir yöntem bulunmamaktadır, ancak üst sınıfında bu yöntem mevcuttur ve üstelik genel erişimlidir: miras yoluyla bu yöntem, enseignant sınıfının genel erişimli bir yöntemi haline gelir. Elde edilen sonuçlar şunlardır:
dos>vbc /r:personne.dll /r:enseignant.dll test.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
dos>test
Construction personne(string, string, int)
Construction enseignant(string,string,int,int)
personne(Jean,Dupont,30)
Görüldüğü gibi:
- personne nesnesi, enseignant nesnesinden önce oluşturulmuştur
- elde edilen kimlik, personne nesnesine aittir
3.2.3. Bir yöntem veya özelliğin aşırı yüklenmesi
Önceki örnekte, öğretmenin personne kısmının kimliğini elde ettik, ancak enseignant sınıfına (bölüm) özgü bazı bilgiler eksik. Bu nedenle, öğretmeni tanımlamaya yarayan bir özellik yazmamız gerekiyor:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
Public Class enseignant
Inherits personne
' özellikler
Private _section As Integer
' oluşturucu
Public Sub New(ByVal P As String, ByVal N As String, ByVal age As Integer, ByVal section As Integer)
MyBase.New(P, N, age)
Me._section = section
' izleme
Console.Out.WriteLine("Construction enseignant(string,string,int,int)")
End Sub
' bölüm özelliği
Public Property section() As Integer
Get
Return _section
End Get
Set(ByVal Value As Integer)
_section = Value
End Set
End Property
' kimlik özelliğinin yeniden tanımlanması
Public Shadows ReadOnly Property identite() As String
Get
Return "enseignant(" & MyBase.identite & "," & _section & ")"
End Get
End Property
End Class
enseignant sınıfının identite yöntemi, ana sınıfının (MyBase.identite) identite yöntemini kullanır "personne" kısmını görüntülemek için kullanır ve ardından enseignant sınıfına özgü olan _section alanıyla tamamlar. identite özelliğinin tanımına dikkat edelim:
Public Shadows ReadOnly Property identite() As String
Bu, identite özelliğinin, üst sınıfta bulunabilecek aynı isimli yöntemi "gizlediğini" gösterir. enseignant E nesnesini ele alalım. Bu nesne, kendi içinde bir personne nesnesi içerir:
![]() |
"identite" özelliği hem enseignant sınıfında hem de üst sınıfı olan personne sınıfında tanımlanmıştır. Alt sınıf olan enseignant'te, identite özelliğinin önüne, enseignant. sınıfı için yeni bir identite özelliğinin yeniden tanımlandığını belirtmek üzere shadows anahtar sözcüğü eklenmelidir
Public Shadows ReadOnly Property identite() As String
enseignant sınıfı artık iki identite özelliğine sahiptir:
- ana sınıftan miras alınan özellik personne
- kendine ait olan
E, bir enseignant nesnesi ise, E.identite, enseignant sınıfının identite yöntemini belirtir. Ana sınıfın identite özelliğinin, alt sınıfın identite özelliği tarafından "yeniden tanımlandığı" söylenir. Genel olarak, O bir nesne ve M bir yöntem ise, O.M yöntemini çalıştırmak için sistem, M yöntemini aşağıdaki sırayla arar:
- O nesnesinin sınıfında
- varsa, üst sınıfında
- varsa, ana sınıfının ana sınıfında
- vb…
Dolayısıyla miras, alt sınıfta üst sınıftaki aynı isimli yöntemleri/özellikleri yeniden tanımlamaya olanak tanır. Bu, alt sınıfın kendi ihtiyaçlarına göre uyarlanmasını sağlar. Biraz sonra ele alacağımız polimorfizmle birleştiğinde, yöntemlerin/özelliklerin aşırı yüklenmesi, mirasın en önemli avantajıdır. Önceki örnekle devam edelim:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
Module test
Sub Main()
Console.Out.WriteLine(New enseignant("Jean", "Dupont", 30, 27).identite)
End Sub
End Module
Bu sefer elde edilen sonuçlar şunlardır:
Construction personne(string, string, int)
Construction enseignant(string,string,int,int)
enseignant(personne(Jean,Dupont,30),27)
3.2.4. Polimorfizm
Şu sınıf dizisini ele alalım: C0 C1 C2 … Burada Ci Cj, Cj sınıfının Ci sınıfından türetildiğini gösterir. Bu, Cj sınıfının Ci sınıfının tüm özelliklerine ek olarak başka özelliklere de sahip olduğu anlamına gelir. Ci türündeki Oi nesneleri olsun. Şu şekilde yazmak geçerlidir:
Nitekim, miras yoluyla Cj sınıfı, Ci sınıfının tüm özelliklerine ek olarak başka özelliklere de sahiptir. Dolayısıyla, Cj türündeki bir Oj nesnesi, kendi içinde Ci türünde bir nesne barındırır. Şu işlem:
işlemi, Oi'nin Oj nesnesinde bulunan Ci türündeki nesneye bir referans olmasını sağlar.
Ci sınıfına ait bir Oi değişkeninin, aslında sadece Ci sınıfına ait bir nesneye değil, aynı zamanda Ci sınıfından türetilmiş herhangi bir nesneye de başvurabilmesi durumuna polimorfizm denir: bir değişkenin farklı nesne türlerine başvurabilme özelliği. Bir örnek verelim ve herhangi bir sınıftan bağımsız olan aşağıdaki fonksiyonu ele alalım:
Sub affiche(ByVal p As personne)
Aşağıdaki şekilde de yazabiliriz:
ya da
Bu son durumda, affiche işlevinin personne türündeki biçimsel parametresi, enseignant türünde bir değer alacaktır. enseignant türü, personne türünden türediği için bu işlem geçerlidir.
3.2.5. Yeniden tanımlama ve polimorfizm
affiche prosedürümüzü tamamlayalım:
Sub affiche(ByVal p As personne)
' p kimliğini göster
Console.Out.WriteLine(p.identite)
End Sub
p.identite yöntemi, personne. nesnesini tanımlayan bir karakter dizisi döndürür. Önceki örneğimizde, enseignant nesnesi söz konusu olduğunda ne olur:
Dim e As New enseignant("Lucile", "Dumas", 56, 61)
affiche(e)
Şu örneği inceleyelim:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
Module test
Sub Main()
' bir öğretmen
Dim e As New enseignant("Lucile", "Dumas", 56, 61)
affiche(e)
' bir kişi
Dim p As New personne("Jean", "Dupont", 30)
affiche(p)
End Sub
' görüntüler
Sub affiche(ByVal p As personne)
' p kimliğini gösterir
Console.Out.WriteLine(p.identite)
End Sub
End Module
Elde edilen sonuçlar şunlardır:
Construction personne(string, string, int)
Construction enseignant(string,string,int,int)
personne(Lucile,Dumas,56)
Construction personne(string, string, int)
personne(Jean,Dupont,30)
Çalıştırma sonucu, p.identite komutunun her seferinde bir personne nesnesinin identite özelliğini çalıştırdığını, enseignant'te bulunan e kişisini ve ardından personne'in kendisini çalıştırdığı görülmektedir. Bu işlem, affiche'e parametre olarak gerçekten geçirilen nesneye uymamıştır. enseignant e nesnesinin tam kimliğini elde etmeyi tercih ederdik. Bunun için p.identite notasyonunun, p tarafından gerçekte işaret edilen nesnenin identite özelliğine atıfta bulunması gerekirdi; "personne" nesnesinin identite özelliğine değil, p tarafından gerçekten işaret edilen nesnenin identite özelliğine atıfta bulunması gerekirdi. Bu sonuca, identite'i temel sınıf personne içinde yeniden tanımlanabilir (overridable) bir özellik olarak bildirerek ulaşılabilir:
Public Overridable ReadOnly Property identite() As String
Get
Return "personne(" & _prenom & "," & _nom & "," & age & ")"
End Get
End Property
overridable anahtar sözcüğü, identite'i yeniden tanımlanabilir veya sanal bir özellik haline getirir. Bu anahtar sözcük, yöntemlere de uygulanabilir. Sanal bir özelliği veya yöntemi yeniden tanımlayan alt sınıflar, yeniden tanımladıkları özellik/yöntemi nitelemek için shadows yerine overrides anahtar sözcüğünü kullanmalıdır. Dolayısıyla, enseignant sınıfında, identite özelliği şu şekilde tanımlanmıştır:
' kimlik özelliğinin üst yazılması
Public Overrides ReadOnly Property identite() As String
Get
Return "enseignant(" & MyBase.identite & "," & _section & ")"
End Get
End Property
Test programı:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
Module test
Sub Main()
' bir öğretmen
Dim e As New enseignant("Lucile", "Dumas", 56, 61)
affiche(e)
' bir kişi
Dim p As New personne("Jean", "Dupont", 30)
affiche(p)
End Sub
' görüntüler
Sub affiche(ByVal p As personne)
' kimlik bilgilerini göster
Console.Out.WriteLine(p.identite)
End Sub
End Module
şu sonuçları verir:
Construction personne(string, string, int)
Construction enseignant(string,string,int,int)
enseignant(personne(Lucile,Dumas,56),61)
Construction personne(string, string, int)
personne(Jean,Dupont,30)
Bu sefer öğretmenin tam kimliğini elde ettik. Şimdi bir özellik yerine bir yöntem tanımlayalım. object sınıfı, tüm VB.NET sınıflarının "ana" sınıfıdır. Dolayısıyla şunu yazdığımızda:
yazdığımızda, dolaylı olarak şunu yazmış oluruz:
object sınıfı, ToString adlı bir sanal yöntem tanımlar:

ToString yöntemi, aşağıdaki örnekte gösterildiği gibi nesnenin ait olduğu sınıfın adını döndürür:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
Module test2
Sub Main()
' bir öğretmen
Console.Out.WriteLine(New enseignant("Lucile", "Dumas", 56, 61).ToString())
' bir kişi
Console.Out.WriteLine(New personne("Jean", "Dupont", 30).ToString())
End Sub
End Module
Elde edilen sonuçlar şunlardır:
Construction personne(string, string, int)
Construction enseignant(string,string,int,int)
enseignant
Construction personne(string, string, int)
personne
personne ve enseignant sınıflarında ToString yöntemini yeniden tanımlamamış olsak da, object sınıfındaki ToString yönteminin yine de nesnenin gerçek sınıf adını görüntüleyebildiğini görebiliriz. personne ve enseignant sınıflarındaki ToString yöntemini yeniden tanımlayalım:
' ToString
Public Overrides Function ToString() As String
' özdeşlik özelliğini tanırız
Return identite
End Function
Tanım her iki sınıfta da aynıdır. Aşağıdaki test programını ele alalım:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
Module test
Sub Main()
' bir öğretmen
Dim e As New enseignant("Lucile", "Dumas", 56, 61)
affiche(e)
' bir kişi
Dim p As New personne("Jean", "Dupont", 30)
affiche(p)
End Sub
' afiş
Sub affiche(ByVal p As personne)
' kimlik bilgilerini göster
Console.Out.WriteLine(p.identite)
End Sub
End Module
Çalıştırma sonuçları şöyledir:
Construction personne(string, string, int)
Construction enseignant(string,string,int,int)
enseignant(personne(Lucile,Dumas,56),61)
Construction personne(string, string, int)
personne(Jean,Dupont,30)
3.3. Bir sınıf için bir indeksleyici tanımlama
.NET platformunda önceden tanımlanmış olan [ArrayList] sınıfını ele alalım. Bu sınıf, nesneleri bir listede saklamaya olanak tanır. Sınıf, [System.Collections] ad alanına aittir. Aşağıdaki örnekte, bu sınıfı (genel anlamıyla) bir kişi listesini saklamak için kullanıyoruz:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
Imports System.Collections
' sınıf listeDePersonnes
Public Class listeDePersonnes
Inherits ArrayList
' listeye kişi eklemek için
Public Overloads Sub Add(ByVal p As personne)
MyBase.Add(p)
End Sub
' bir indeksleyici
Default Public Shadows Property Item(ByVal i As Integer) As personne
Get
Return CType(MyBase.Item(i), personne)
End Get
Set(ByVal Value As personne)
MyBase.Item(i) = Value
End Set
End Property
' başka bir indeksleyici
Default Public Shadows ReadOnly Property Item(ByVal N As String) As Integer
Get
' N adlı kişiyi arıyoruz
Dim i As Integer
For i = 0 To Count - 1
If CType(Me(i), personne).nom = N Then
Return i
End If
Next i
Return -1
End Get
End Property
' toString
Public Overrides Function ToString() As String
' (el1, el2, ..., eln) değerlerini döndürür
Dim liste As String = "("
Dim i As Integer
' dinamik diziyi tarıyoruz
For i = 0 To (Count - 2)
liste += "[" + Me(i).ToString + "]" + ","
Next i 'for
' son eleman
If Count <> 0 Then
liste += "[" + Me(i).ToString + "]"
End If
liste += ")"
Return liste
End Function
End Class
[ArrayList] sınıfının bazı özellikleri ve yöntemleri hakkında birkaç bilgi verelim:
Listenin eleman sayısını veren özellik | |
listeye bir nesne eklemeye yarayan yöntem | |
listenin i numaralı öğesini veren yöntem |
Listedeki i numaralı öğeyi elde etmek için [liste.Item(i)] yazmadığımızı, bunun yerine doğrudan [liste(i)] yazdığımızı fark ediyoruz; bu ilk bakışta hatalı gibi görünüyor. Bununla birlikte bu mümkündür, çünkü [ArrayList] sınıfı, aşağıdaki sözdizimine benzer şekilde [Item] adlı bir varsayılan özellik tanımlamaktadır:
Default Public Property Item(ByVal i As Integer) As Object
Get
...
End Get
Set(ByVal Value As personne)
...
End Set
End Property
Derleyici, [liste(i)] notasyonuyla karşılaştığında, [ArrayList] sınıfının aşağıdaki imzaya sahip bir özellik tanımlayıp tanımlamadığını arar:
Default Public Property Proc(ByVal var As Integer) As Type
Burada, [Item] yordamını bulacaktır. Ardından, [liste(i)] yazımını [liste.Item(i)] olarak çevirecektir. [Item] özelliğine, [ArrayList] sınıfının varsayılan indeksli özelliği denir. Yukarıdaki programın çalıştırılması aşağıdaki sonuçları verir:
dos>vbc /r:personne.dll /r:enseignant.dll lstpersonnes1.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
dos>dir
11/03/2004 18:26 3 584 enseignant.dll
12/03/2004 15:34 3 584 lstpersonnes1.exe
12/03/2004 13:39 661 lstpersonnes1.vb
11/03/2004 18:26 4 096 personne.dll
dos>lstpersonnes1
Construction personne(string, string, int)
Construction personne(string, string, int)
Construction personne(string, string, int)
Construction enseignant(string,string,int,int)
personne(paul,chenou,31)
personne(nicole,chenou,11)
enseignant(personne(jacques,sileau,33),61)
[listeDePersonnes] adlı bir sınıf oluşturalım; bu sınıf, bir kişi listesi olacak, yani [ArrayList] sınıfından türetilmesi doğal görünen özel bir liste olacaktır:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
Imports System.Collections
' sınıf listeDePersonnes
Public Class listeDePersonnes
Inherits ArrayList
' listeye bir kişi eklemek için
Public Shadows Sub Add(ByVal p As Object)
' p'nin bir kişi olması gerekir
If Not TypeOf (p) Is personne Then
Throw New Exception("L'objet ajouté (" + p.ToString + ") n'est pas une personne")
Else
MyBase.Add(p)
End If
End Sub
' bir indeksleyici
Default Public Shadows Property Index(ByVal i As Integer) As personne
Get
Return CType(MyBase.Item(i), personne)
End Get
Set(ByVal Value As personne)
MyBase.Item(i) = Value
End Set
End Property
' toString
Public Overrides Function ToString() As String
' (el1, el2, ..., eln) değerini döndürür
Dim liste As String = "("
Dim i As Integer
' dinamik diziyi tarar
For i = 0 To (Count - 2)
liste += "[" + Me(i).ToString + "]" + ","
Next i 'for
' son eleman
If Count <> 0 Then
liste += "[" + Me(i).ToString + "]"
End If
liste += ")"
Return liste
End Function
End Class
Sınıf, aşağıdaki yöntemleri ve özellikleri içerir:
listenin içeriğini "temsil eden" bir karakter dizesi döndürür | |
Listeye bir kişi eklemeye yarayan yöntem | |
listeye i numaralı kişiyi veren varsayılan indeksli özellik |
Yeni noktaları ele alalım:
Yeni bir yöntem olan [Add] oluşturulmuştur.
' listeye bir kişi eklemek için
Public Shadows Sub Add(ByVal p As Object)
' p'nin bir kişi olması gerekir
If Not TypeOf (p) Is personne Then
Throw New Exception("L'objet ajouté (" + p.ToString + ") n'est pas une personne")
Else
MyBase.Add(p)
End If
End Sub
Aynı imzaya sahip, üst sınıf [ArrayList]'te zaten bir tane mevcut olduğundan, yeni yordamın üst sınıftakini değiştirdiğini belirtmek için [Shadows] anahtar sözcüğü kullanılmıştır. Alt sınıftaki [Add] yöntemi, eklenen nesnenin gerçekten [personne] türünde olup olmadığını veya [TypeOf] işleviyle türetilmiş olup olmadığını kontrol eder. Aksi takdirde, [Throw] komutuyla bir istisna atılır. Eklenen nesne gerçekten [personne] türündeyse, ekleme işlemi için temel sınıfın [Add] yöntemi kullanılır.
Bir indeksli özellik oluşturulur:
' bir indeksleyici
Default Public Shadows Property Index(ByVal i As Integer) As personne
Get
Return CType(MyBase.Item(i), personne)
End Get
Set(ByVal Value As personne)
MyBase.Item(i) = Value
End Set
End Property
Temel sınıfta aynı imzaya sahip [Item] adlı bir varsayılan özellik zaten mevcuttur. Bu nedenle, yeni indeksli özellik [Index]'in temel sınıftaki [Item] özelliğini "gizleyeceğini" belirtmek için [Shadows] anahtar sözcüğünü kullanmak zorundayız. Her iki özelliğin adı aynı olmasa bile bu durumun geçerli olduğu unutulmamalıdır. [Index] özelliği, listedeki i numaralı kişiye referans verilmesini sağlar. Bu özellik, altta yatan [ArrayList] nesnesinin i numaralı öğesine erişmek için temel sınıfın [Item] özelliğine dayanır. [Item] özelliğinin [Object] türündeki öğelerle çalışırken, [Index] özelliğinin ise [personne] türündeki öğelerle çalıştığı dikkate alınarak tür değişiklikleri yapılmıştır.
Son olarak, [ArrayList] sınıfının [ToString] yöntemini yeniden tanımlıyoruz (Overrides):
' toString
Public Overrides Function ToString() As String
' (el1, el2, ..., eln) değerini döndürür
Dim liste As String = "("
Dim i As Integer
' dinamik diziyi tarar
For i = 0 To (Count - 2)
liste += "[" + Me(i).ToString + "]" + ","
Next i 'for
' son eleman
If Count <> 0 Then
liste += "[" + Me(i).ToString + "]"
End If
liste += ")"
Return liste
End Function
Bu yöntem, "(e1,e2,...,en)" biçiminde bir karakter dizesi döndürür; burada ei, listenin elemanlarıdır. [Me(i)] notasyonu, geçerli nesne [Me]'in i numaralı elemanını belirtir. Burada varsayılan indeksli özellik kullanılır. Dolayısıyla [Me(i)], [Me.Index(i)] ile eşdeğerdir.
Sınıf kodu, [lstpersonnes2.vb] dosyasına yerleştirilir ve derlenir:
dos>dir
11/03/2004 18:26 3 584 enseignant.dll
12/03/2004 15:45 970 lstpersonnes2.vb
11/03/2004 18:26 4 096 personne.dll
dos>vbc /r:personne.dll /r:enseignant.dll /t:library lstpersonnes2.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
dos>dir
11/03/2004 18:26 3 584 enseignant.dll
12/03/2004 15:50 3 584 lstpersonnes2.dll
12/03/2004 15:45 970 lstpersonnes2.vb
11/03/2004 18:26 4 096 personne.dll
Bir test programı oluşturulur:
' seçenekler
Option Explicit On
Option Strict On
' ad alanları
Imports System
Imports System.Collections
Module test
Sub Main()
' boş bir kişi listesi oluşturma
Dim liste As listeDePersonnes = New listeDePersonnes
' kişilerin oluşturulması
Dim p1 As personne = New personne("paul", "chenou", 31)
Dim p2 As personne = New personne("nicole", "chenou", 11)
Dim e1 As enseignant = New enseignant("jacques", "sileau", 33, 61)
' listenin doldurulması
liste.Add(p1)
liste.Add(p2)
liste.Add(e1)
' listenin görüntülenmesi
Console.Out.WriteLine(liste.ToString)
' kişi dışındaki bir nesnenin eklenmesi
Try
liste.Add(4)
Catch e As Exception
Console.Error.WriteLine(e.Message)
End Try
End Sub
End Module
Derlenir:
dos>vbc /r:personne.dll /r:enseignant.dll /r:lstpersonnes2.dll test.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
dos>dir
11/03/2004 18:26 3 584 enseignant.dll
12/03/2004 15:50 3 584 lstpersonnes2.dll
12/03/2004 15:45 970 lstpersonnes2.vb
11/03/2004 18:26 4 096 personne.dll
12/03/2004 15:50 3 584 test.exe
12/03/2004 15:49 623 test.vb
ve ardından şu komut çalıştırıldı:
dos>test
Construction personne(string, string, int)
Construction personne(string, string, int)
Construction personne(string, string, int)
Construction enseignant(string,string,int,int)
([personne(paul,chenou,31)],[personne(nicole,chenou,11)],[enseignant(personne(jacques,sileau,33),61)])
L'objet ajouté (4) n'est pas une personne
Şöyle yazmak isteyebiliriz
burada l, [listeDePersonnes] türünde olacaktır. Burada, l listesini artık bir öğe numarasıyla değil, bir kişi adıyla indekslemek istiyoruz. Bunun için varsayılan olarak indekslenen yeni bir özellik tanımlıyoruz:
' başka bir indeksleyici
Default Public Shadows ReadOnly Property Item(ByVal N As String) As Integer
Get
' N adlı kişi aranıyor
Dim i As Integer
For i = 0 To Count - 1
If CType(Me(i), personne).nom = N Then
Return i
End If
Next i
Return -1
End Get
End Property
İlk satır
Default Public Shadows ReadOnly Property Index(ByVal N As String) As Integer
, varsayılan olarak indekslenen yeni bir özellik oluşturulduğunu gösterir. Tüm varsayılan özellikler aynı adı taşımalıdır; burada bu isim [Index]'tir. Yeni [Index] özelliği, listeDePersonnes sınıfını N karakter dizisiyle indeksler. listeDePersonnes(N) ifadesinin sonucu bir tamsayıdır. Bu tamsayı, N adını taşıyan kişinin listedeki konumunu gösterir; bu kişi listede yoksa -1 değerini verir. Yalnızca get özelliği tanımlanır; böylece listeDePersonnes yazımı engellenir ("nom")=valeur ise set özelliğinin tanımlanmasını gerektirecekti). Bu nedenle [ReadOnly] anahtar sözcüğü kullanılır. [Shadows] anahtar sözcüğü, temel sınıfın varsayılan özelliğini gizlemek için gereklidir (aynı imzaya sahip olmasa da).
get işlevinin gövdesinde, parametre olarak geçirilen N adını bulmak için kişi listesi taranır. Eğer i konumunda bulunursa i değeri döndürülür, aksi takdirde -1 döndürülür.
Yeni bir test programı şu şekilde olabilir:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
' test sayfası
Module test
Sub Main()
' kişi listesi
Dim l As New listeDePersonnes
' kişi ekleme
l.Add(New personne("jean", "dumornet", 10))
l.Add(New personne("pauline", "duchemin", 12))
' görüntüleme
Console.Out.WriteLine(("l=" + l.ToString))
l.Add(New personne("jacques", "tartifume", 27))
Console.Out.WriteLine(("l=" + l.ToString))
' 1. öğeyi değiştirme
l(1) = New personne("sylvie", "cachan", 5)
' 1. öğeyi görüntüleme
Console.Out.WriteLine(("l[1]=" + l(1).ToString))
' liste görüntüleme l
Console.Out.WriteLine(("l=" + l.ToString))
' kişi arama
Dim noms() As String = New [String]() {"cachan", "inconnu"}
Dim i As Integer
For i = 0 To noms.Length - 1
Dim inom As Integer = l(noms(i))
If inom <> -1 Then
Console.Out.WriteLine(("personne(" & noms(i) & ")=" & l(inom).ToString))
Else
Console.Out.WriteLine(("personne(" + noms(i) + ") n'existe pas"))
End If
Next i
End Sub
End Module
Çalıştırıldığında şu sonuçlar elde edilir:
personne(string, string, int)
Construction personne(string, string, int)
l=([personne(jean,dumornet,10)],[personne(pauline,duchemin,12)])
Construction personne(string, string, int)
l=([personne(jean,dumornet,10)],[personne(pauline,duchemin,12)],[personne(jacques,tartifume,27)])
Construction personne(string, string, int)
l[1]=personne(sylvie,cachan,5)
l=([personne(jean,dumornet,10)],[personne(sylvie,cachan,5)],[personne(jacques,tartifume,27)])
personne(cachan)=personne(sylvie,cachan,5)
personne(inconnu) n'existe pas
3.4. Yapılar
VB.NET yapısı, doğrudan C dilinin yapısından türetilmiştir ve sınıfa çok yakındır. Bir yapı şu şekilde tanımlanır:
Structure spersonne
' özellikler
...
' özellikler
...
' yapıcılar
...
' yöntemler
End Structure
Beyan şekilleri benzer olsa da, sınıf ve yapı arasında önemli farklılıklar vardır. Örneğin, yapılarda miras kavramı yoktur. Türetilmemesi gereken bir sınıf yazarsak, ikisi arasında seçim yapmamıza yardımcı olacak yapı ve sınıf arasındaki farklar nelerdir? Bunu öğrenmek için aşağıdaki örneği inceleyelim:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
' spersonne yapısı
Structure spersonne
Public nom As String
Public age As Integer
End Structure
' csersonne sınıfı
Class cpersonne
Public nom As String
Public age As Integer
End Class
' bir test modülü
Public Module test
Sub Main()
' bir kişi p1
Dim sp1 As spersonne
sp1.nom = "paul"
sp1.age = 10
Console.Out.WriteLine(("sp1=spersonne(" & sp1.nom & "," & sp1.age & ")"))
' bir kişi p2
Dim sp2 As spersonne = sp1
Console.Out.WriteLine(("sp2=spersonne(" & sp2.nom & "," & sp2.age & ")"))
' sp2 değiştirildi
sp2.nom = "nicole"
sp2.age = 30
' sp1 ve sp2'nin doğrulanması
Console.Out.WriteLine(("sp1=cpersonne(" & sp1.nom & "," & sp1.age & ")"))
Console.Out.WriteLine(("sp2=cpersonne(" & sp2.nom & "," & sp2.age & ")"))
' bir kişi cp1
Dim cp1 As New cpersonne
cp1.nom = "paul"
cp1.age = 10
Console.Out.WriteLine(("cP1=cpersonne(" & cp1.nom & "," & cp1.age & ")"))
' bir cpersonne P2
Dim cp2 As cpersonne = cp1
Console.Out.WriteLine(("cP2=cpersonne(" & cp2.nom & "," & cp2.age & ")"))
' P2 değiştirildi
cp2.nom = "nicole"
cp2.age = 30
' P1 ve P2'in doğrulanması
Console.Out.WriteLine(("cP1=cpersonne(" & cp1.nom & "," & cp1.age & ")"))
Console.Out.WriteLine(("cP2=cpersonne(" & cp2.nom & "," & cp2.age & ")"))
End Sub
End Module
Bu programı çalıştırdığımızda şu sonuçlar elde edilir:
sp1=spersonne(paul,10)
sp2=spersonne(paul,10)
sp1=cpersonne(paul,10)
sp2=cpersonne(nicole,30)
cP1=cpersonne(paul,10)
cP2=cpersonne(paul,10)
cP1=cpersonne(nicole,30)
cP2=cpersonne(nicole,30)
Bu bölümün önceki sayfalarında personne sınıfı kullanılırken, artık spersonne yapısını kullanıyoruz:
' kişi yapısı
Structure spersonne
Public nom As String
Public age As Integer
End Structure
Beyanname
Dim sp1 As spersonne
bir yapı (ad, yaş) oluşturur ve sp1'in değeri bu yapının kendisidir.
Aşağıdaki tanımlama
Dim cp1 As New cpersonne
bir [cpersonne] nesnesi oluşturur (kabaca bizim yapımızın karşılığı) ve cp1 ise bu nesnenin adresi (referansı) olur.
Özetleyelim
- yapı söz konusu olduğunda, sp1'in değeri yapının kendisidir
- sınıf söz konusu olduğunda, p1'in değeri oluşturulan nesnenin adresidir
![]() |
![]() |
Programda şu kod yazıldığında
Dim sp2 As spersonne = sp1
yazıldığında, yeni bir yapı (ad, yaş) oluşturulur ve p1 değeri, yani yapının kendisi ile başlatılır.
![]() |
Böylece sp1'deki yapı sp2'ye kopyalanır. Bu, değerlerin kopyalanmasıdır.
Şu komut
Dim cp2 As cpersonne = cp1
farklı şekilde çalışır. cp1'in değeri cp2'ye kopyalanır, ancak bu değer aslında nesnenin adresi olduğu için nesne kopyalanmaz. Sadece nesneye iki referans eklenir:
![]() |
Yapı durumunda, sp2 değerini değiştirirsek, sp1 değerini değiştirmiş olmayız; program da bunu göstermektedir. Nesne durumunda ise, cp2 tarafından işaret edilen nesne değiştirilirse, cp1 tarafından işaret edilen nesne de aynı olduğu için değiştirilir. Programın sonuçları da bunu göstermektedir.
Dolayısıyla bu açıklamalardan şunu çıkarabiliriz:
- yapı türündeki bir değişkenin değeri, yapının kendisidir
- nesne türündeki bir değişkenin değeri, işaret edilen nesnenin adresidir
Bu temel fark anlaşıldıktan sonra, yapı, aşağıdaki yeni örnekte de görüldüğü gibi sınıfa çok benzemektedir:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
' kişi yapısı
Structure personne
' özellikler
Private _nom As String
Private _age As Integer
' özellikler
Public Property nom() As String
Get
Return _nom
End Get
Set(ByVal Value As String)
_nom = value
End Set
End Property
Public Property age() As Integer
Get
Return _age
End Get
Set(ByVal Value As Integer)
_age = value
End Set
End Property
' Oluşturucu
Public Sub New(ByVal NOM As String, ByVal AGE As Integer)
_nom = NOM
_age = AGE
End Sub 'New
' TOSTRING
Public Overrides Function ToString() As String
Return "personne(" & nom & "," & age & ")"
End Function
End Structure
' bir test modülü
Module test
Sub Main()
' bir kişi p1
Dim p1 As New personne("paul", 10)
Console.Out.WriteLine(("p1=" & p1.ToString))
' bir kişi p2
Dim p2 As personne = p1
Console.Out.WriteLine(("p2=" & p2.ToString))
' p2 değiştirildi
p2.nom = "nicole"
p2.age = 30
' p1 ve p2'nin doğrulanması
Console.Out.WriteLine(("p1=" & p1.ToString))
Console.Out.WriteLine(("p2=" & p2.ToString))
End Sub
End Module
Aşağıdaki yürütme sonuçları elde edilir:
Burada yapı ile sınıf arasındaki tek belirgin fark, bir sınıf kullanıldığında p1 ve p2 nesnelerinin programın sonunda p2'nin değeriyle aynı değere sahip olacağıdır.
3.5. Arayüzler
Bir arayüz, bir sözleşme oluşturan yöntem veya özellik prototiplerinden oluşan bir kümedir. Bir arayüzü uygulamaya karar veren bir sınıf, arayüzde tanımlanan tüm yöntemlerin bir uygulamasını sağlamayı taahhüt eder. Bu uygulamayı denetleyen derleyicidir. Örneğin, Istats arayüzünün tanımı şöyledir:
Bu arayüzü uygulayan tüm sınıflar şu şekilde tanımlanacaktır:
public class C
Implements Istats
...
function moyenne() as Double Implements Istats.moyenne
...
end function
function écartType () as Double Implements Istats. écartType
...
end function
end class
[moyenne] ve [écartType] yöntemleri C sınıfında tanımlanmalıdır. Aşağıdaki kodu ele alalım:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
' yapı
Public Structure élève
Public _nom As String
Public _note As Double
' yapıcı
Public Sub New(ByVal NOM As String, ByVal NOTE As Double)
Me._nom = NOM
Me._note = NOTE
End Sub
End Structure
' sınıf notları
Public Class notes
' özellik
Protected _matière As String
Protected _élèves() As élève
' üretici
Public Sub New(ByVal MATIERE As String, ByVal ELEVES() As élève)
' öğrenci ve ders bilgileri
Me._matière = MATIERE
Me._élèves = ELEVES
End Sub
' ToString
Public Overrides Function ToString() As String
Dim valeur As String = "matière=" + _matière + ", notes=("
Dim i As Integer
' tüm notları birleştiriyoruz
For i = 0 To (_élèves.Length - 1) - 1
valeur &= "[" & _élèves(i)._nom & "," & _élèves(i)._note & "],"
Next i
'son not
If _élèves.Length <> 0 Then
valeur &= "[" & _élèves(i)._nom & "," & _élèves(i)._note & "]"
End If
valeur += ")"
' son
Return valeur
End Function
End Class
notes sınıfı, bir dersteki sınıf notlarını bir araya getirir:
Public Class notes
' özellik
Protected _matière As String
Protected _élèves() As élève
Özellikler, türetilmiş bir sınıftan erişilebilir olması için protected olarak tanımlanmıştır. élève türü, öğrencinin adını ve o dersteki notunu depolayan bir yapıdır:
Public Structure élève
Public _nom As String
Public _note As Double
' oluşturucu
Public Sub New(ByVal NOM As String, ByVal NOTE As Double)
Me._nom = NOM
Me._note = NOTE
End Sub
End Structure
Bu notes sınıfını, notların ortalaması ve standart sapması olmak üzere iki ek özniteliğe sahip notesStats sınıfına dönüştürmeye karar veriyoruz:
Public Class notesStats
Inherits notes
Implements Istats
' özellikler
Private _moyenne As Double
Private _écartType As Double
notesStats sınıfı, aşağıdaki Istats arayüzünü uygular:
Bu, notesStats sınıfının, moyenne ve écartType adlı iki yönteme sahip olması ve bu yöntemlerin imzalarının Istats arayüzünde belirtilen şekilde olması gerektiği anlamına gelir. notesStats sınıfı şu şekildedir:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
Public Class notesStats
Inherits notes
Implements Istats
' özellikler
Private _moyenne As Double
Private _écartType As Double
' oluşturucu
Public Sub New(ByVal MATIERE As String, ByVal ELEVES() As élève)
MyBase.New(MATIERE, ELEVES)
' not ortalaması hesaplama
Dim somme As Double = 0
Dim i As Integer
For i = 0 To ELEVES.Length - 1
somme += ELEVES(i)._note
Next i
If ELEVES.Length <> 0 Then
_moyenne = somme / ELEVES.Length
Else
_moyenne = -1
End If
' standart sapma
Dim carrés As Double = 0
For i = 0 To ELEVES.Length - 1
carrés += Math.Pow(ELEVES(i)._note - _moyenne, 2)
Next i
If ELEVES.Length <> 0 Then
_écartType = Math.Sqrt((carrés / ELEVES.Length))
Else
_écartType = -1
End If
End Sub
' ToString
Public Overrides Function ToString() As String
Return MyBase.ToString() & ",moyenne=" & _moyenne & ",écart-type=" & _écartType
End Function 'ToString
' Istats arayüzü yöntemleri
Public Function moyenne() As Double Implements Istats.moyenne
' not ortalamasını verir
Return _moyenne
End Function
Public Function écartType() As Double Implements Istats.écartType
' standart sapmayı hesaplar
Return _écartType
End Function
End Class
_moyenne ortalaması ve _ecartType standart sapması, nesnenin oluşturulduğu anda hesaplanır. Bu nedenle, moyenne ve écartType yöntemleri, yalnızca _moyenne ve _ecartType özniteliklerinin değerlerini döndürür. Öğrenci tablosu boşsa, her iki yöntem de -1 değerini döndürür.
Aşağıdaki test sınıfı:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
Module test
Sub Main()
' bazı öğrenciler ve notlar
Dim ELEVES() As élève = {New élève("paul", 14), New élève("nicole", 16), New élève("jacques", 18)}
' bunların bir not nesnesine kaydedilmesi
Dim anglais As New notes("anglais", ELEVES)
' ve görüntülenir
Console.Out.WriteLine((anglais.ToString))
' aynı işlem, ortalama ve standart sapma ile
anglais = New notesStats("anglais", ELEVES)
Console.Out.WriteLine((anglais.ToString))
End Sub
End Module
şu sonuçları verir:
matière=anglais, notes=([paul,14],[nicole,16],[jacques,18])
matière=anglais, notes=([paul,14],[nicole,16],[jacques,18]),moyenne=16,écart-type=1,63299316185545
notesStats sınıfı, moyenne ve écartType yöntemlerini, Istats arayüzünü uyguladığını belirtmeden kendi başına gayet iyi bir şekilde uygulayabilirdi. Arayüzlerin ne gibi bir faydası vardır? Şu şekildedir: Bir işlev, I arayüzünün türüne sahip bir veriyi biçimsel parametre olarak kabul edebilir. Böylece, I arayüzünü uygulayan C sınıfına ait herhangi bir nesne, bu işlevin gerçek parametresi olabilir. Aşağıdaki örneği ele alalım:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
' bir Iexample arayüzü
Public Interface Iexemple
Function ajouter(ByVal i As Integer, ByVal j As Integer) As Integer
Function soustraire(ByVal i As Integer, ByVal j As Integer) As Integer
End Interface
' birinci sınıf
Public Class classe1
Implements Iexemple
Public Function ajouter(ByVal a As Integer, ByVal b As Integer) As Integer Implements Iexemple.ajouter
Return a + b + 10
End Function
Public Function soustraire(ByVal a As Integer, ByVal b As Integer) As Integer Implements Iexemple.soustraire
Return a - b + 20
End Function
End Class
'ikinci sınıf
Public Class classe2
Implements Iexemple
Public Function ajouter(ByVal a As Integer, ByVal b As Integer) As Integer Implements Iexemple.ajouter
Return a + b + 100
End Function
Public Function soustraire(ByVal a As Integer, ByVal b As Integer) As Integer Implements Iexemple.soustraire
Return a - b + 200
End Function
End Class
Iexemple arayüzü, ajouter ve soustraire adlı iki yöntem tanımlar. classe1 ve classe2 sınıfları bu arayüzü uygular. Örneği basitleştirmek amacıyla bu sınıfların başka hiçbir şey yapmadığına dikkat edilmelidir. Şimdi şu örneği ele alalım:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
' test sınıfı
Module test
'hesapla
Sub calculer(ByVal i As Integer, ByVal j As Integer, ByVal inter As Iexemple)
Console.Out.WriteLine(inter.ajouter(i, j))
Console.Out.WriteLine(inter.soustraire(i, j))
End Sub
' Main işlevi
Sub Main()
' sınıf1 ve sınıf2 adlı iki nesnenin oluşturulması
Dim c1 As New classe1
Dim c2 As New classe2
' calculer statik işlevinin çağrılması
calculer(4, 3, c1)
calculer(14, 13, c2)
End Sub
End Module
calculer işlevi, Iexemple türünde bir öğeyi parametre olarak kabul eder. Dolayısıyla bu parametre için hem classe1 hem de classe2 türünde bir nesne alabilir. Main yordamında bu işlem gerçekleştirilir ve aşağıdaki sonuçlar elde edilir:
Görüldüğü üzere, burada sınıflar için ele alınan polimorfizme benzer bir özellik söz konusudur. Eğer birbirleriyle miras yoluyla bağlantılı olmayan (dolayısıyla miras polimorfizmi kullanılamayan) bir Ci sınıflar kümesi, aynı imzaya sahip bir yöntemler kümesi sunuyorsa, bu yöntemleri ilgili tüm sınıfların miras alacağı bir I arayüzünde bir araya getirmek faydalı olabilir. Bu Ci sınıflarının örnekleri, I türünde bir parametre kabul eden fonksiyonların parametreleri olarak kullanılabilir, c.a.d. Bu fonksiyonlar, farklı Ci sınıflarının kendine özgü özelliklerini ve yöntemlerini değil, yalnızca I arayüzünde tanımlanan Ci nesnelerinin yöntemlerini kullanır. Son olarak, arayüzlerden çoklu miras alınabileceğini belirtelim, c.a.d. Şu şekilde yazılabilir:
Public Class classe
Implements I1,I2,...
burada Ij'ler arayüzlerdir.
3.6. Ad alanları
Ekrana bir satır yazmak için şu komutu kullanırız:
Console sınıfının tanımına bakarsak
Namespace: System
Assembly: Mscorlib (in Mscorlib.dll)
gördüğümüz gibi, bu sınıf System ad alanının bir parçasıdır. Bu, Console sınıfının System.Console olarak adlandırılması gerektiği anlamına gelir ve aslında şöyle yazmamız gerekir:
Bunu, imports cümlesini kullanarak önleyebiliriz:
System ad alanının, imports cümlesi ile içe aktarıldığı söylenir. Derleyici bir sınıf adına (burada Console) rastladığında, imports cümleleriyle içe aktarılan çeşitli ad alanlarında bu sınıfı arayacaktır. Burada, System ad alanında Console sınıfını bulacaktır. Şimdi, Console sınıfına ekli ikinci bilgiye dikkat edelim:
Assembly: Mscorlib (in Mscorlib.dll)
Bu satır, Console sınıfının tanımının hangi "derlemede" bulunduğunu gösterir. Visual Studio.NET dışında derleme yaparken ve kullanılması gereken sınıfları içeren farklı dll'lerin referanslarını belirtmek gerektiğinde bu bilgi yararlı olabilir. Bir sınıfın derlenmesi için gerekli olan dll'lere referans vermek için şu şekilde yazılır:
Bir sınıf oluşturulurken, bu sınıf bir ad alanı içinde oluşturulabilir. Bu ad alanlarının amacı, örneğin sınıflar satıldığında sınıflar arasında ad çakışmalarını önlemektir. Sırasıyla dll, E1.dll ve E2.dll paketlerinde dağıtılan sınıfları dağıtan iki şirket olduğunu varsayalım. C adlı bir müşteri, her iki şirketin de personne sınıfını tanımladığı bu iki sınıf kümesini satın alsın. C adlı müşteri, bir programı şu şekilde derler:
prog.vb kaynak dosyası personne sınıfını kullanıyorsa, derleyici, personne sınıfını E1.dll'ten mi yoksa E2.dll'ten mi alması gerektiğini bilemeyecektir. Bir hata bildirir. Eğer E1 şirketi sınıflarını E1 adlı bir ad alanında, E2 şirketi ise E2 adlı bir ad alanında oluşturursa, o zaman her iki personne sınıfı, sırasıyla E1.personne ve E2.personne olarak adlandırılacaktır. Müşteri, sınıflarında ya E1.personne ya da E2.personne'i kullanmalıdır, ancak personne'i kullanmamalıdır. Ad alanı, belirsizliği ortadan kaldırmaya yarar. Bir ad alanında sınıf oluşturmak için şu şekilde yazılır:
Namespace istia.st
Public Class personne
' sınıfın tanımlanması
...
end Class
end Namespace
Örnek olarak, daha önce incelediğimiz personne sınıfımızı bir ad alanında oluşturalım. Ad alanı olarak istia.st'i seçeceğiz. personne sınıfı şu şekilde olur:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
' istia.st ad alanının oluşturulması
Namespace istia.st
Public Class personne
' özellikler
Private prenom As String
Private nom As String
Private age As Integer
' yöntem
Public Sub initialise(ByVal P As String, ByVal N As String, ByVal age As Integer)
Me.prenom = P
Me.nom = N
Me.age = age
End Sub
' yöntem
Public Sub identifie()
Console.Out.WriteLine((prenom & "," & nom & "," & age))
End Sub
End Class
End Namespace
Bu sınıf, personne.dll olarak derlenir:
dos>vbc /t:library personne.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
Şimdi personne sınıfını bir test sınıfında kullanalım:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
Imports istia.st
' pg testi
Public Module test
Sub Main()
Dim p1 As New personne
p1.initialise("Jean", "Dupont", 30)
p1.identifie()
End Sub
End Module
Şunu yazmaktan kaçınmak için
Dim p1 As New istia.st.personne
yazmak zorunda kalmamak için, istia.st ad alanını bir imports cümlesiyle içe aktardık:
Imports istia.st
Şimdi test programını derleyelim:
dos>dir
12/03/2004 18:06 3 584 personne.dll
11/03/2004 18:27 610 personne.vb
12/03/2004 18:05 254 test.vb
dos>vbc /r:personne.dll test.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
dos>dir
12/03/2004 18:06 3 584 personne.dll
11/03/2004 18:27 610 personne.vb
12/03/2004 18:08 3 072 test.exe
12/03/2004 18:05 254 test.vb
Bu işlem, test.exe adlı bir dosya oluşturur ve bu dosya çalıştırıldığında aşağıdaki sonuçlar elde edilir:
3.7. IMPOTS örneği
Bir önceki bölümde incelenen vergi hesaplamasını tekrar ele alalım ve bunu bir sınıf kullanarak işleyelim. Sorunu hatırlayalım:
Sadece maaşını beyan edecek bir vergi mükellefinin basitleştirilmiş durumunu ele alalım:
- çalışanın pay sayısını şu şekilde hesaplıyoruz: nbParts = nbEnfants/2 + 1 (evli değilse), evliyse nbEnfants/2+2 olarak hesaplanır; burada nbEnfants, çocuk sayısıdır.
- En az üç çocuğu varsa, yarım pay daha eklenir
- vergilendirilebilir geliri R=0,72*S olarak hesaplanır; burada S, yıllık maaşıdır
- aile katsayısı QF = R/nbParts olarak hesaplanır
- Vergisi I hesaplanır. Aşağıdaki tabloyu ele alalım:
12620,0 | 0 | 0 |
13190 | 0,05 | 631 |
15640 | 0,1 | 1290,5 |
24.740 | 0,15 | 2072,5 |
31810 | 0,2 | 3309,5 |
39.970 | 0,25 | 4900 |
48360 | 0,3 | 6898,5 |
55790 | 0,35 | 9316,5 |
92970 | 0,4 | 12106 |
127.860 | 0,45 | 16754,5 |
151250 | 0,50 | 23147,5 |
172.040 | 0,55 | 30710 |
195.000 | 0,60 | 39312 |
0 | 0,65 | 49062 |
Her satırda 3 alan vardır. I vergisini hesaplamak için, QF<=alan1 olan ilk satır aranır. Örneğin, QF=23000 ise şu satır bulunur:
bulunur. I vergisi bu durumda 0,15*R - 2072,5*nbParts'e eşittir. Eğer QF, QF<=alan1 ilişkisini hiçbir zaman karşılamıyorsa, o zaman son satırdaki katsayılar kullanılır. Burada:
bu da I=0,65*R - 49062*nbParts vergi tutarını verir.
impot sınıfı şu şekilde tanımlanacaktır:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
Public Class impot
' vergi hesaplaması için gerekli veriler
' harici bir kaynaktan alınmıştır
Private limites(), coeffR(), coeffN() As Decimal
' üretici
Public Sub New(ByVal LIMITES() As Decimal, ByVal COEFFR() As Decimal, ByVal COEFFN() As Decimal)
' 3 tablonun da aynı boyutta olup olmadığı kontrol edilir
Dim OK As Boolean = LIMITES.Length = COEFFR.Length And LIMITES.Length = COEFFN.Length
If Not OK Then
Throw New Exception("Les 3 tableaux fournis n'ont pas la même taille(" & LIMITES.Length & "," & COEFFR.Length & "," & COEFFN.Length & ")")
End If
' sorun yok
Me.limites = LIMITES
Me.coeffR = COEFFR
Me.coeffN = COEFFN
End Sub
' vergi hesaplaması
Public Function calculer(ByVal marié As Boolean, ByVal nbEnfants As Integer, ByVal salaire As Long) As Long
' pay sayısının hesaplanması
Dim nbParts As Decimal
If marié Then
nbParts = CDec(nbEnfants) / 2 + 2
Else
nbParts = CDec(nbEnfants) / 2 + 1
End If
If nbEnfants >= 3 Then
nbParts += 0.5D
End If
' Vergilendirilebilir gelir ve aile katsayısı hesaplaması
Dim revenu As Decimal = 0.72D * salaire
Dim QF As Decimal = revenu / nbParts
' vergi hesaplaması
limites((limites.Length - 1)) = QF + 1
Dim i As Integer = 0
While QF > limites(i)
i += 1
End While
Return CLng(revenu * coeffR(i) - nbParts * coeffN(i))
End Function
End Class
Bir vergi nesnesi, bir vergi mükellefinin vergisinin hesaplanmasına olanak tanıyan verilerle oluşturulur. Bu, nesnenin sabit kısmıdır. Bu nesne oluşturulduktan sonra, vergi mükellefinin medeni durumu (evli veya bekar), çocuk sayısı ve yıllık maaşına göre vergisini hesaplayan **calculer** yöntemini tekrar tekrar çağırabiliriz. Bir test programı şu şekilde olabilir:
' seçenekler
Option Strict On
Option Explicit On
' ad alanları
Imports System
Imports Microsoft.VisualBasic
Module test
Sub Main()
' etkileşimli vergi hesaplama programı
' kullanıcı klavyeden üç veri girer: evli nbEnfants maaş
' program daha sonra ödenecek vergiyi gösterir
Const syntaxe As String = "syntaxe : marié nbEnfants salaire" + ControlChars.Lf + "marié : o pour marié, n pour non marié" + ControlChars.Lf + "nbEnfants : nombre d'enfants" + ControlChars.Lf + "salaire : salaire annuel en F"
' vergi hesaplaması için gerekli veri tabloları
Dim limites() As Decimal = {12620D, 13190D, 15640D, 24740D, 31810D, 39970D, 48360D, 55790D, 92970D, 127860D, 151250D, 172040D, 195000D, 0D}
Dim coeffR() As Decimal = {0D, 0.05D, 0.1D, 0.15D, 0.2D, 0.25D, 0.3D, 0.35D, 0.4D, 0.45D, 0.5D, 0.55D, 0.6D, 0.65D}
Dim coeffN() As Decimal = {0D, 631D, 1290.5D, 2072.5D, 3309.5D, 4900D, 6898.5D, 9316.5D, 12106D, 16754.5D, 23147.5D, 30710D, 39312D, 49062D}
' bir vergi nesnesinin oluşturulması
Dim objImpôt As impot = Nothing
Try
objImpôt = New impot(limites, coeffR, coeffN)
Catch ex As Exception
Console.Error.WriteLine(("L'erreur suivante s'est produite : " + ex.Message))
Environment.Exit(1)
End Try
' sonsuz döngü
Dim marié As String
Dim nbEnfants As Integer
Dim salaire As Long
While True
' vergi hesaplaması için parametreler isteniyor
Console.Out.Write("Paramètres du calcul de l'impôt au format marié nbEnfants salaire ou rien pour arrêter :")
Dim paramètres As String = Console.In.ReadLine().Trim()
' Yapılması gereken bir şey var mı?
If paramètres Is Nothing OrElse paramètres = "" Then
Exit While
End If
' giriş satırındaki argüman sayısının kontrolü
Dim erreur As Boolean = False
Dim args As String() = paramètres.Split(Nothing)
Dim nbParamètres As Integer = args.Length
If nbParamètres <> 3 Then
Console.Error.WriteLine(syntaxe)
erreur = True
End If
' parametrelerin geçerliliğinin kontrolü
If Not erreur Then
' evli
marié = args(0).ToLower()
If marié <> "o" And marié <> "n" Then
erreur = True
End If
' nbEnfants
Try
nbEnfants = Integer.Parse(args(1))
If nbEnfants < 0 Then
Throw New Exception
End If
Catch
erreur = True
End Try
' maaş
Try
salaire = Integer.Parse(args(2))
If salaire < 0 Then
Throw New Exception
End If
Catch
erreur = True
End Try
End If
' parametreler doğruysa - vergi hesaplanır
If Not erreur Then
Console.Out.WriteLine(("impôt=" & objImpôt.calculer(marié = "o", nbEnfants, salaire) & " F"))
Else
Console.Error.WriteLine(syntaxe)
End If
End While
End Sub
End Module
İşte önceki programın çalıştırılmasına ilişkin bir örnek:
dos>vbc /t:library impots.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
dir>dir
12/03/2004 18:24 4 096 impots.dll
12/03/2004 18:20 1 483 impots.vb
12/03/2004 18:21 2 805 test.vb
dos>vbc /r:impots.dll test.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
dos>dir
12/03/2004 18:24 4 096 impots.dll
12/03/2004 18:20 1 483 impots.vb
12/03/2004 18:26 6 144 test.exe
12/03/2004 18:21 2 805 test.vb
dos>test
Paramètres du calcul de l'impôt au format marié nbEnfants salaire ou rien pour arrêter :x x x
syntaxe : marié nbEnfants salaire
marié : o pour marié, n pour non marié
nbEnfants : nombre d'enfants
salaire : salaire annuel en F
Paramètres du calcul de l'impôt au format marié nbEnfants salaire ou rien pour arrêter :o 2 200000
impôt=22504 F
Paramètres du calcul de l'impôt au format marié nbEnfants salaire ou rien pour arrêter :





