1. Anasayfa
  2. 100 Günde Solidity

🧵 #100GündeSolidity 025 : Miras Alma ve Gölgeleme

Solidity'de Miras Alma ve Shadowing: State Variable'ların Güvenli Kullanımı

🧵 #100GündeSolidity 025 : Miras Alma ve Gölgeleme
Miras Alma ve Gölgeleme
0

Miras Alma ve Gölgeleme (Shadowing Inherited State Variables)

Solidity, Ethereum platformu için akıllı sözleşmeler oluşturmak için kullanılan bir programlama dilidir. Solidity, nesne yönelimli bir dil olup, diğer programlama dillerinde olduğu gibi kalıtım (inheritance) yapısını destekler. Ancak, kalıtım yapısı bazı sorunlara neden olabilir. Bu sorunlardan biri de “Shadowing Inherited State Variables” olarak adlandırılır. Bu sorun, state variable’ları miras alan bir alt sınıfta, aynı isimde yeni bir state variable tanımlandığında ortaya çıkar. Bu durumda, alt sınıfın kendi state variable’ı, üst sınıfın state variable’ını gölgeler ve istenmeyen sonuçlara neden olabilir. Bu makalede, “Shadowing Inherited State Variables” konusunu ele alacak ve shadowing’in neden olduğu sorunları, shadowing’i önlemek için kullanılabilecek yöntemleri ve en iyi uygulama yöntemlerini örneklerle açıklayacağız.

Miras alma (Inheritance) kavramı ve Solidity’de nasıl kullanıldığına bakalım.

Miras alma (inheritance), bir sınıfın, başka bir sınıftan özelliklerini (fonksiyonlar ve değişkenler gibi) miras almasıdır. Bu özellikler, miras alan sınıf tarafından kullanılabilir ve gerekliyse değiştirilebilir. Solidity’de de nesne yönelimli programlama prensipleri çerçevesinde inheritance yapıları desteklenir.

Solidity’de inheritance yapısı, “is” anahtar kelimesi ile belirtilir. Örneğin, aşağıdaki şekildeki gibi bir Contract1 sınıfının Contract2 sınıfı tarafından miras alınması durumunu ele alalım:

contract Contract1 {
  uint public x;
}

contract Contract2 is Contract1 {
  function getX() public view returns (uint) {
    return x;
  }
}

Yukarıdaki örnekte, Contract2, Contract1 sınıfını miras almıştır. Bu nedenle, Contract2 sınıfı, Contract1 sınıfının public state variable’ını, fonksiyonlarını vb. kullanabilir.

Inheritance yapıları, Solidity’de akıllı sözleşmelerde sıkça kullanılır ve kod tekrarını azaltmaya yardımcı olur. Ancak, inheritance yapısı da, “Shadowing Inherited State Variables” gibi sorunlara neden olabilir.

State variable’ların nasıl miras alındığı ve kullanıldığına bakalım.

State variable’lar, Solidity’de bir sözleşmenin durumunu ve verilerini depolamak için kullanılan değişkenlerdir. Inheritance yapılarıyla bir sözleşme, başka bir sözleşmeden state variable’larını miras alabilir.

Bir sözleşmenin state variable’ları, sözleşmenin içinde tanımlanır ve “public”, “private”, “internal” veya “external” olabilir. “Public” state variable’lar, herkes tarafından erişilebilirken, “private” ve “internal” state variable’lar sadece sözleşme içinde erişilebilirler.

Inheritance yapısı kullanılarak, alt sınıf, üst sınıfın state variable’larını miras alabilir ve kendi state variable’larını ekleyebilir. Aşağıdaki örnekte, Contract2, Contract1 sınıfından bir state variable miras almış ve kendi state variable’ını da eklemiştir:

contract Contract1 {
  uint public x;
}

contract Contract2 is Contract1 {
  uint public y;
}

Yukarıdaki örnekte, Contract2, Contract1 sınıfının public state variable’ını miras almıştır ve aynı zamanda kendi public state variable’ını da tanımlamıştır. Bu sayede, Contract2 sınıfı, hem Contract1 sınıfının public state variable’ına hem de kendi public state variable’ına erişebilir.

“Shadowing” kavramı ve state variable’ları shadow etmenin ne anlama geldiğine bakalım.

“Shadowing”, inheritance yapısıyla bir sınıfın, üst sınıftan miras aldığı state variable’ını, aynı isimde bir başka state variable ile gölgelemesi anlamına gelir. Yani alt sınıf, üst sınıfın state variable’ını, aynı isimde bir state variable tanımlayarak örtbas eder ve üst sınıfın state variable’ı artık kullanılamaz hale gelir.

Shadowing, Solidity’de state variable’lar için kullanılamaz. Ancak, bir alt sınıf, üst sınıfın state variable’ını, aynı isimde bir fonksiyonla gölgeleyebilir. Bu durum, bazen programcılar tarafından istenilir ve fonksiyonun üst sınıftan miras alınan halini değiştirmeye olanak tanır.

Aşağıdaki örnekte, Contract2 sınıfı, Contract1 sınıfından miras aldığı x() fonksiyonunu gölgelemiş ve kendi x() fonksiyonunu tanımlamıştır:

contract Contract1 {
  uint public x;
  function x() public pure returns (uint) {
    return 1;
  }
}

contract Contract2 is Contract1 {
  function x() public pure returns (uint) {
    return 2;
  }
}

Yukarıdaki örnekte, Contract2, Contract1 sınıfının x() fonksiyonunu gölgelemiş ve kendi x() fonksiyonunu tanımlamıştır. Bu sayede, Contract2 sınıfı, x() fonksiyonunu kullanırken, kendi tanımladığı x() fonksiyonu çalışacaktır ve üst sınıftan miras alınan x() fonksiyonu kullanılamaz hale gelecektir.

Shadowing’in nasıl bir soruna yol açabileceği ve dikkat edilmesi gereken durumlara bakalım.

Shadowing, Solidity’de özellikle dikkat edilmesi gereken bir konudur, çünkü yanlış kullanımı istenmeyen sonuçlara yol açabilir.

Shadowing, alt sınıfın, üst sınıfın state variable veya fonksiyonlarını gizlemesiyle sonuçlanır. Bu durum, özellikle büyük proje kodlarında, programcıların hangi değişken veya fonksiyonun kullanıldığını takip etmesini zorlaştırır. Böylece, Shadowing kullanırken, özellikle büyük projelerde, kodların okunabilirliğini ve bakımını kolaylaştırmak için dikkatli olmak gerekir.

Ayrıca, Shadowing kullanırken, üst sınıfın state variable veya fonksiyonunun işlevselliğinin tamamen değiştirilmesi durumunda, alt sınıfın beklenmeyen hatalara yol açabilir. Bu nedenle, bir sınıfın üst sınıfından miras alınan state variable veya fonksiyonları değiştirmeden önce, bunların nasıl kullanıldığını ve alt sınıfta neden değiştirilmesi gerektiğini iyi anlamak önemlidir.

Sonuç olarak, Shadowing kullanırken, özellikle büyük proje kodlarında, kodların okunabilirliğini ve bakımını kolaylaştırmak ve beklenmeyen hataları önlemek için dikkatli olmak gerekir.

Solidity’de “override” ve “super” keyword’lerinin nasıl kullanıldığı ve shadowing’i önlemek için nasıl kullanılabileceğine bakalım.

Solidity’de “override” ve “super” keyword’leri, shadowing’i önlemek ve üst sınıftan miras alınan fonksiyonların işlevselliğini değiştirmek için kullanılabilir.

“override” keyword’ü, bir alt sınıfın üst sınıftan miras aldığı bir fonksiyonu, aynı isimde ve imza ile tekrar tanımlamasına olanak tanır. Bu sayede, alt sınıf, üst sınıfın fonksiyonunu gölgelemek yerine, aynı isimde ve imza ile bir fonksiyon tanımlayarak, fonksiyonun işlevselliğini değiştirebilir.

“super” keyword’ü ise, bir alt sınıfın, üst sınıftan miras aldığı bir fonksiyonu, değiştirdikten sonra, üst sınıfın fonksiyonunu da çağırmasına olanak tanır. Böylece, alt sınıf, üst sınıfın fonksiyonunun işlevselliğini değiştirebilirken, üst sınıfın fonksiyonunu da kullanarak, shadowing’i önleyebilir.

Aşağıdaki örnek, “override” ve “super” keyword’lerinin nasıl kullanılabileceğini gösterir:

contract Contract1 {
  uint public x;
  function foo() public virtual {
    x = 1;
  }
}

contract Contract2 is Contract1 {
  function foo() public virtual override {
    // Contract1'in foo fonksiyonunu çağırır
    super.foo(); 
    x = x + 1; // x değişkenine 1 ekler
  }
}

Yukarıdaki örnekte, Contract2 sınıfı, Contract1 sınıfından miras aldığı “foo” fonksiyonunu “override” keyword’ü ile tekrar tanımlamıştır. Ayrıca, “super” keyword’ü ile, alt sınıfın “foo” fonksiyonu, üst sınıfın “foo” fonksiyonunu çağırmıştır. Böylece, alt sınıf, üst sınıfın fonksiyonunu kullanarak, x değişkenine 1 eklemiş ve shadowing’i önlemiştir.

Sonuç olarak, “override” ve “super” keyword’leri, Solidity’de shadowing’i önlemek ve üst sınıftan miras alınan fonksiyonların işlevselliğini değiştirmek için kullanılabilir. Ancak, bu keyword’lerin dikkatli bir şekilde kullanılması ve üst sınıfın işlevselliğinin tamamen değiştirilmemesi önemlidir.

En iyi uygulama yöntemleri ve örneklerle açıklayalım.

Solidity’de miras alma ve shadowing konularında en iyi uygulama yöntemleri aşağıdaki gibi sıralanabilir:

  1. Shadowing yerine override kullanın: State variable’ları shadow etmek yerine, alt sınıfta aynı isim ve imza ile fonksiyonları override etmek daha iyidir. Böylece, alt sınıfın fonksiyonu, üst sınıfın fonksiyonunu tamamen değiştirmek yerine, üst sınıfın fonksiyonunu kullanarak, ek işlevselliği sağlayabilir.
  2. State variable’ların isimlendirilmesinde dikkatli olun: State variable’ların isimlendirilmesinde, miras alma yapılan üst sınıftaki isimlerle aynı isimleri kullanmaktan kaçının. Bu, shadowing’e neden olabilir ve beklenmedik sonuçlara yol açabilir.
  3. Sınıf hiyerarşisini basitleştirin: Sınıf hiyerarşisini basitleştirmek, shadowing ve override problemlerini önlemek için önemlidir. Aşırı miras alma kullanmak yerine, daha az sayıda sınıf kullanmaya çalışın.
  4. İsim çakışmalarına dikkat edin: Alt sınıfın kullanacağı yeni bir isim kullanırken, isim çakışması olmadığından emin olun. Ayrıca, farklı sınıflarda kullanılan isimleri birbirinden ayırt edici yapmak için sınıf adlarını kullanabilirsiniz.

Aşağıdaki örnek, shadowing’i önlemek ve miras alma yöntemlerini uygulamak için nasıl kullanılabileceğini gösterir:

contract Vehicle {
    uint public numWheels;
    
    constructor(uint _numWheels) {
        numWheels = _numWheels;
    }
    
    function start() public virtual {
        // Vehicle sınıfının start fonksiyonu
    }
}

contract Car is Vehicle {
    uint public numDoors;
    
    constructor(uint _numWheels, uint _numDoors) Vehicle(_numWheels) {
        numDoors = _numDoors;
    }
    
    function start() public virtual override {
        super.start();
        // Car sınıfının start fonksiyonu
    }
}

contract Truck is Vehicle {
    uint public payloadCapacity;
    
    constructor(uint _numWheels, uint _payloadCapacity) Vehicle(_numWheels) {
        payloadCapacity = _payloadCapacity;
    }
    
    function start() public virtual override {
        super.start();
        // Truck sınıfının start fonksiyonu
    }
}

contract SportsCar is Car {
    string public model;
    
    constructor(uint _numDoors, string memory _model) Car(4, _numDoors) {
        model = _model;
    }
    
    function start() public override {
        super.start();
        // SportsCar sınıfının start fonksiyonu
    }
}

Yukarıdaki örnekte, “Vehicle” sınıfı, “numWheels” adında bir state variable’a sahiptir ve “start” adında bir fonksiyon tanımlar. “Car

” sınıfı “Vehicle” sınıfını miras almıştır ve “numDoors” adında başka bir state variable’a sahiptir. “Car” sınıfında, “start” fonksiyonu override edilir ve “super.start()” ifadesi, “Vehicle” sınıfındaki “start” fonksiyonunun çağrılmasını sağlar.

“Truck” sınıfı da “Vehicle” sınıfını miras almıştır ve “payloadCapacity” adında bir state variable’a sahiptir. “Truck” sınıfında, “start” fonksiyonu override edilir ve yine “super.start()” ifadesi, “Vehicle” sınıfındaki “start” fonksiyonunun çağrılmasını sağlar.

“SportsCar” sınıfı da “Car” sınıfını miras almıştır ve “model” adında bir state variable’a sahiptir. “SportsCar” sınıfında, “start” fonksiyonu override edilir ve “super.start()” ifadesi, “Car” sınıfındaki “start” fonksiyonunun çağrılmasını sağlar.

Bu örnekte, sınıflar hiyerarşik bir yapıda düzenlenmiştir. “start” fonksiyonu override edilerek, sınıfların kendi işlevselliğini gerçekleştirebilmesi sağlanmıştır. “super” anahtar kelimesi, alt sınıfların üst sınıflardaki fonksiyonların işlevselliğini kullanmasına olanak tanırken, “override” anahtar kelimesi, alt sınıfların üst sınıflardaki fonksiyonların işlevselliğini değiştirebilmesine izin verir. Bu sayede, shadowing problemleri önlenmiş ve sınıf hiyerarşisi basitleştirilmiştir.

Örnek Akıllı Sözleşme Örneği İncelemesi

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract A {
    string public name = "Contract A";

    function getName() public view returns (string memory) {
        return name;
    }
}

// Shadowing is disallowed in Solidity 0.6
// This will not compile
// contract B is A {
//     string public name = "Contract B";
// }

contract C is A {
    // This is the correct way to override inherited state variables.
    constructor() {
        name = "Contract C";
    }

    // C.getName returns "Contract C"
}

Bu örnekte, “A” adında bir sözleşme tanımlanmıştır. Bu sözleşmenin “name” adında bir public state variable’ı ve “getName” adında bir fonksiyonu vardır. “getName” fonksiyonu, “name” state variable’ını döndürür.

Daha sonra, “C” adında bir sözleşme tanımlanmıştır ve “A” sözleşmesini miras almıştır. “C” sözleşmesinde, “name” state variable’ı override edilmemiştir. Bunun yerine, “name” state variable’ının değeri, “C” sözleşmesinin constructor’ında değiştirilmiştir. Bu, “C” sözleşmesinin “getName” fonksiyonunu çağırdığında, “Contract C” değerini döndürmesini sağlar.

Bu örnekte, “B” adında başka bir sözleşme tanımlamak ve “name” state variable’ını override etmek istendiğinde, Solidity 0.6’da shadowing’in yasak olduğunu hatırlatmak için yorum satırı ile belirtilmiştir. “C” sözleşmesindeki “name” state variable’ını değiştirmek, override etmek yerine, shadowing yaparak kodun anlaşılmasını zorlaştırabilir ve hatalara neden olabilir.

Sonuç Bağlamı

Bu makalede, Solidity programlama dilinde miras alma kavramı ve state variable’ların miras alınması ele alınmıştır. Ayrıca, miras alınan state variable’ların shadowing ile nasıl sorunlara yol açabileceği ve bu sorunları önlemek için “override” ve “super” keyword’lerinin nasıl kullanılabileceği incelenmiştir. Son olarak, en iyi uygulama yöntemleri ve örnekler verilerek, Solidity geliştiricilerinin bu konuda dikkatli olmaları gerektiği vurgulanmıştır. Miras alma, Solidity’de kodun yeniden kullanılabilirliğini artıran güçlü bir özelliktir, ancak doğru kullanılmadığında hatalara ve sorunlara neden olabilir. Bu nedenle, Solidity programlama dilinde miras alma ve shadowing konularına hakim olmak, Solidity geliştiricileri için önemlidir.

Solidity Programlama Dili Öğrenme yolculuğunuz hakkında daha iyi rehberlik almak için Solidity nedir? Ethereum Akıllı Sözleşmelerinin Dili Rehberi içeriğimize göz atın. Dilerseniz Yeni Başlayanlar için Solidity – Akıllı Sözleşme Geliştirme Hızlandırılmış Kursuna katılın.

Çalışmaya nereden başlayacağım diyenler için Blockchain ​​Developer Olmak İçin Yol Haritası içeriğine de muhakkak bakın.

Gelin aklınızdaki soruları SUPERPEER sohbetinde cevaplayalım.

Bu makaleyi okuduğunuz için teşekkürler! Bana destek olmak isterseniz;

Beni TwitterLinkedin ve YouTube‘da takip edin.

Kısa bir yorum bırakmayı UNUTMAYIN!

solidity101 - Solidity, 2015 yılında Christian Reitwiessner liderliğinde piyasaya sürülen, büyük harf kullanımına göre ikinci en büyük kripto para piyasası olan Ethereum tarafından oluşturulan yepyeni bir programlama dilidir.

Yazarın Profili
İlginizi Çekebilir

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir