Nesne yönelimli programlama (NYP) | Object Oriented Programming (OOP)

Seda Kayademir
7 min readAug 24, 2020

--

Nedir?

Her işlevin nesneler olarak soyutlandığı bir programlama yaklaşımıdır. NYP destekleyen programlama dilleri yüksek seviye diller olarak adlandırılır. En yaygın NYP dillerinden bazıları, Python, C++, Objective-C, Smalltalk, Delphi, Java, Swift, C#, Perl, Ruby ve PHP’ dir.

Bu yazıda kavramları gerçekleştirmek için Python dilini kullanacağız.

OOP teorisinde 4 temel özelliğin gerçekleştirilmesi zorunlu sayılmıştır ve biri bile eksik ise bu dil saf OOP sayılmamıştır. Bunlar:

  • Encapsulation
  • Inheritance
  • Polymorphism
  • Abstraction

Temel Kavramlar

Nesne (Object) ve Sınıf (Class) Nedir?

Sınıflardan üretilen her değişkene nesne adı verilir. Sınıf nesnelerin özelliklerini(attribute) ve davranışlarını(method) saklayan yapılardır.

Sınıf class anahtar kelimesi ile tanımlanır.

In [1]:

class Square: # Sınıf class anahtar kelimesi ile tanımlanır.
pass # Sınıfın içeriğini daha sonra tanımlamak için kullanılır.

In [2]:

square = Square()
square # object(nesne)

Out[2]:

<__main__.Square at 0x7f1fa8776410>

Nitelikler / Attribute

class class_name:

attribute1

attribute2

In [3]:

class Square:
edge = 5 # attribute

In [4]:

square = Square()
square.edge # özelikklere erişmek

Out[4]:

5

In [5]:

square.edge = 7 # özelliğe yeni değer atanması. 
#Özelliğin bu şekilde değiştirlmesi nesne yönelimli programa uygun düşmez.
#Bunun engellenmesi gerekir.
square.edge

Out[5]:

7

Metotlar / Methods

class class_name:

attribute1

def method_name:

In [6]:

class Square():
edge = 5
area = 0

def area_calculate(self):
# self sınıfın özelliklerine erişmemizi sağlar. Belirtilmediği durumda hata verir.
self.area = self.edge * self.edge
print("Area =", self.area)

In [7]:

square = Square()
print(square.edge)
print(square.area)
square.area_calculate()
5
0
Area = 25

Fonksiyon ve metot arasındaki fark

Fonksiyonlar sınıflar dışında tanımlanır, metotlar ise sınıfların içinde tanımlanır ve self parametresini alır.

In [8]:

def area_calculate_function(edge): # Fonksiyon, sınıftan bağımsız çalışır.
area = edge * edge
print("Area =", area)

In [9]:

area_calculate_function(7)Area = 49

Eğer fonksiyon ile hesaplanan değeri farklı bir işlemde kullanmamız gerekiyorsa return ile hesaplan değeri dışarı aktarabiliriz.

In [10]:

def area_calculate_function(edge): 
area = edge * edge
print("Area =", area)
return area

In [11]:

area = area_calculate_function(6)
print(area)
Area = 36
36

Yapılandırcı / Initializer or Constructor

Yapılandırıcıların (constructor) görevi oluşturulan nesneyi ilk kullanıma hazırlamasıdır. Python’da init anahtar kelimesi ile initializer tanımlanır.

In [12]:

class Animals(object):
def __init__(self, name, age):
self.name = name
self.age = age

def getAge(self):
return self.age
def getName(self):
print(self.name)

In [13]:

animal1 =  Animals('dog', 2)
animal2 = Animals('cat', 5)

In [14]:

print("Animal-1 Info: ", animal1.name, animal1.age)
print("Animal-2 Info: ", animal2.name, animal2.age)
Animal-1 Info: dog 2
Animal-2 Info: cat 5

Dört Temel Özelliğin

  • Encapsulation
  • Inheritance
  • Polymorphism
  • Abstraction

1.Kapsülleme / Encapsulation

Nesne yönelimli programlamanın ilk prensibi kapsülleme (encapsulation) olarak adlandırılır. Bu özellik, dilin nesne kullanıcısından gereksiz uygulama ayrıntılarını saklar. Oluşturulan bir sınıf (class) içerisinde kullanıcının işlemlerini daha kolay gerçekleştirebilmesi için bazı işlemler birleştirilerek tek bir işlem gibi gösterilir. Bu birleştirme işlemine kapsülleme denir.

Erişim belirteçleri (access modifier) sayesinde kapsülleme çok daha kolay yapılmaktadır. Erişim belirteçleri, oluşturulan sınıf veya sınıf içindeki elemanların erişim seviyelerini belirlemek için kullanılan anahtar kelimeler grubuna verilen isimdir. Metotlar ve değişkenler bir anahtar sözcük ile önceden bellirlenen sınırlar dahilinde kullanılabilir. Bu anahtar kelimeler şu şekilde sıralanabilir.

  • public(global): Sistemdeki bütün sınıfların erişebilmesini sağlar. Yalnızca aynı proje içinden değil, diğer projelerden de erişim sağlanabilir.
  • private: Bir “özellik (property)”in veya “metod”un sadece tanımlandığı sınıftan erişilebilmesini sağlar.
  • protected: Sadece tanımlandığı sınıfın içinde ve o sınıftan türetilmiş diğer sınıfların içinde erişilebilir.

Python’da nesneye erişim kısıtlaması koymak için değişkenin ismin başına __ işareti eklenir. Belirtilmediği durumda değişken global olarak kabul edilir.

In [15]:

class BankAccount():
def __init__(self, name, money):
self.name = name #public
self.__money = money #private

In [16]:

ali = BankAccount("Ali", 2000)
ali.name

Out[16]:

'Ali'

In [17]:

ali.money---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-17-35412f66a497> in <module>
----> 1 ali.money
AttributeError: 'BankAccount' object has no attribute 'money'

In [18]:

# Private özelliklere erişmek için get ve set fonksiyonları kullanılır.
class BankAccount():
def __init__(self, name, money):
self.name = name
self.__money = money

def getMoney(self): # Değişkene ulaşmak için kullanılır.
return self.__money

def setMoney(self, amount): # Değişkene değer ataması için kulllanılır.
self.__money = amount

def increase(self):
self.__money = self.__money + 100

In [19]:

veli = BankAccount('veli', 4000)
veli.getMoney()

Out[19]:

4000

In [20]:

veli.setMoney(4500)
veli.getMoney()

Out[20]:

4500

Private methods

In [21]:

veli.increase()
veli.getMoney()

Out[21]:

4600

In [22]:

class BankAccount():
def __init__(self, name, money):
self.name = name
self.__money = money

def getMoney(self):
return self.__money

def setMoney(self, amount):
self.__money = amount
#private method
def __increase(self):
self.__money = self.__money + 100

In [23]:

oya = BankAccount('Oya', 3000)
oya.increase()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-23-e5147198dadb> in <module>
1 oya = BankAccount('Oya', 3000)
----> 2 oya.increase()
AttributeError: 'BankAccount' object has no attribute 'increase'

2.Miras / Inheritance

Nesne Yönelimli Programlama (Object Oriented Programming) dillerindeki ana prensiplerinden biri Miras(Inheritance) kavramıdır. Bir sınıfın özelliklerinin ve metotlarının başka sınıflara aktarılarak işlevinin artırılmasını sağlar. Oluşturulan ve genel özellikler içeren ilk sınıfa temel sınıf (parent class), ondan miras alınarak özelleştirilen alt sınıflara türetilmiş sınıflar (child class) denir. Miras kavramı, birbirlerine benzeyen sınıfları tek tek yazmak yerine, ortak üyeleri belirleyerek bir temel sınıf oluşturmak ve geri kalanlarını bu sınıftan türetmek gibi pratik bir yol sunar.

In [24]:

# parent
class Animals:
def __init__(self):
print("animal is created")
def toString(self):
print("animal")
def walk(self):
print("animal walk")

In [25]:

# child
class Monkey(Animals):
def __init__(self):
super().__init__() # Temel(ana) sınıfın __init__ metotunu kullandığını belirmek için kullanılır.
print("monkey is created")
def toString(self):
print("monkey")
# extend
def climb(self):
print("monkey can climb")

In [26]:

monkey = Monkey() # Animal sınıfının __init__ metotunu kullandıanimal is created
monkey is created

In [27]:

monkey.toString()monkey

In [28]:

monkey.walk()animal walk

In [29]:

monkey.climb()monkey can climb

In [30]:

# child
class Brid(Animals):
def __init__(self):
Animals.__init__(self) # super yerine bu şekilde de kullanılabilir.
print("bird is created")
def toString(self):
super().toString() # Temel(ana) sınıfın herhangi metotunu için de kullanılabilir.
print("bird")
# extend
def fly(self):
("bird can climb")

In [31]:

bird = Brid()
bird.toString()
animal is created
bird is created
animal
bird

In [32]:

bird.climb() # clibm sadeve Monkey sınıfına ait olduğu için erişilemez.---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-32-d727ce9a6312> in <module>
----> 1 bird.climb() # clibm sadeve Monkey sınıfına ait olduğu için erişilemez.
AttributeError: 'Brid' object has no attribute 'climb'

3.Soyut Sınıflar / Abstract Classes

Nesne tabanlı programlamada sınıf hiyerarşisi oluşturulurken, bazen en tepede bulunan sınıf türünden nesneler programcılar için anlamlı olmayabilir. Hiyerarşinin en tepesinde bulunan sınıfın kendisinden türetilecek olan alt sınıflar için ortak bir arayüz (interface) görevi yapması istenebilir. Bunun için çözüm olarak oluşturulan metotlara ve sınıflara soyut metot (abstract method) ya da soyut sınıf (abstract class) denir. Soyut sınıflar büyük projelerde kullanılırlar ve kalıtım özelliğini kullanarak kod tekrarını azaltırlar. Soyut sınıflar diğer sınıflara taban olmak için kullanılırlar. Nesne türetemezler. Önlerine “abstract” sözcüğü yazılarak soyutlaştırılırlar. Önlerine “virtual” yazılmaz çünkü “abstract” sözcüğü uygulanan tüm sınıf ve metotlar zaten sanaldır.

Kullanırken dikkat edilmesi gerekenler:

Soyut sınıflar “abstract” türünden nesneler tanımlamazlar.

In [33]:

from abc import ABC, abstractclassmethod
class Animals(ABC): # Abstract Base Class (ABC) -> Soyut sınıf olduğunu belirtmek için miras alınır.
@abstractclassmethod # metodun soyut olduğunu belirmek için kullanılır.
def walk(self):
pass
@abstractclassmethod
def run(self):
pass
animal = Animals() # Soyut sınıf olduğu için nesne üretemedik.---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-33-f11658647595> in <module>
8 pass
9
---> 10 animal = Animals() # Soyut sınıf olduğu için nesne üretemedik.
TypeError: Can't instantiate abstract class Animals with abstract methods run, walk

Soyut metotlar override edilmek zorundadırlar, aksi takdirde derleyici hatası alınır.

In [34]:

class Bird(Animals):
def __init__(self):
print("bird")

bird = Bird()
# Soyut sınıftan miras aldığı için soyut sınıfta tanımlanan metotların
# burada tanımlanması gerekir tanımlanmadığı durumda hata dönderir.
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-34-04fd352055b6> in <module>
3 print("bird")
4
----> 5 bird = Bird()
6 # Soyut sınıftan miras aldığı için soyut sınıfta tanımlanan metotların
7 # burada tanımlanması gerekir tanımlanmadığı durumda hata dönderir.
TypeError: Can't instantiate abstract class Bird with abstract methods run, walk

In [35]:

class Bird(Animals):
def __init__(self):
print("bird")
def walk(self):
print("walk")
def run(self):
print("run")

bird = Bird()
bird

Soyut sınıflar içerilerinde soyut olmayan metotlar da barındırabilir ancak soyut metotlar sadece soyut sınıflar içerisinde bildirilebilir.

In [36]:

class Bird(Animals):
def __init__(self):
print("bird")
def walk(self):
print("walk")
def run(self):
print("run")
@abstractclassmethod
def fly(self):
print("fly")

bird = Bird()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-36-ee4be90cc5b4> in <module>
10 print("fly")
11
---> 12 bird = Bird()
TypeError: Can't instantiate abstract class Bird with abstract methods fly

Soyut sınıf ve arayüz arasındaki farklar ve benzerlikler:

  • Arayüz içerisindeki tüm öğelerin “public” olması gerekirken soyut sınıflarda tüm öğelerin “public” olması zorunlu değildir.
  • Bir sınıf sadece bir soyut sınıftan miras olarak tanımlanabilir ancak birçok arayüz tarafından bildirilebilir.
  • Soyut sınıf ve arayüz için yazılacak olan soyut metotların gövdeleri bulunmaz.
  • Soyut sınıflar çoklu ortamı desteklemezler ancak arayüz destekler.
  • Soyut sınıflar kullanım hızı açısından arayüzden daha avantajlıdır.
  • Soyut bir sınıfın tüm metotları soyut yapılırsa arayüz olarak kullanılabilir.
  • Geçersiz Kılmak / Overriding

Nesne Yönelimli (Object Oriented) Programlama’da, ana sınıftaki bazı metodlara, o sınıftan türetilen yeni sınıflarda ihtiyaç duyulmayabilir ya da bu metodlar üzerinde değişiklikler yapılması gerekebilir. Bu durum genellikle yazılan kodun, bir temel sınıf ve bu sınıftan türetilmiş farklı sınıfları etkileyeceği zamanlarda ortaya çıkar ve Overriding (geçersiz kılma) kullanılarak çözülebilir.

In [37]:

#parent 
class Animals:
def toString(self):
print("animal")
#child
class Monkey(Animals):
def toString(self):
print("monkey")

In [38]:

animal = Animals()
animal.toString()
animal

In [39]:

monkey = Monkey()
monkey.toString()
monkey

4.Çok Biçimlilik / Polymorphism

Polymorphism (çok biçimlilik) nesne yönelimli programlamada programlama dilinin farklı tip verileri ve sınıfları farklı şekilde işleme yeteneğini belirten özelliğidir. Daha belirgin olmak gerekirse, metotları ve türetilmiş sınıfları yeniden tanımlama yeteneğidir

In [40]:

class Employee:
def raisee(self):
raise_rate = 0.1
return 100 + 100 * raise_rate

class EEE(Employee):
def raisee(self):
raise_rate = 0.2
return 100 + 100 * raise_rate

class CE(Employee):
def raisee(self):
raise_rate = 0.3
return 100 + 100 * raise_rate

In [41]:

emp = Employee()
ce = CE()
eee = EEE()

In [42]:

emp.raisee()

Out[42]:

110.0

In [43]:

eee.raisee()

Out[43]:

120.0

In [44]:

ce.raisee()

Out[44]:

130.0

Kaynaklar

--

--