Overriding Vs Shadowing

Java ile kod yazarken çok can yakacak bir konuya değinmek istiyorum: Overriding & shadowing. Çok biçimlilik(polyformisim) ve Kalıtımda(-inheritance- sınıflar arası miras) genel konsept değişkenlerin maskelenmesi, metodların ise override edilmesidir. Bu kavram "variables are shadowed and methods are overridden" olarak literatürde de yer almıştır. Yani bir sınıfı extend ettiğimizde sınıfta varolan aynı isimdeki değişkenlerin her alt sınıfla üstü örtülürken(aslında hala yaşamakta ve erişilebilir olmaktadırlar) metodlar için tam bir üstüne yazma işlemi gerçekleşir. ([1]Yine metod signature için bu override işlemi de yeterli değildir ve ilkel sınıf referansı ile gelişmiş nesne metodlarına erişirken temel sınıf metodunun fırlattığı checked exceptionları ele almak gerekir.)

Static değişkenler ve metodlar içinse durum daha farklıdır. Static olarak belirtilmiş değişkenler yine maskelenmiş olarak tutulurken (shadowed) bu kez metodlar da override edilemez ve shadowed olarak her sınıfta farklı metodmuş gibi davranırlar. Zaten @Override annotasyonu da bu durumlar içindir. Zorunlu bir annotation olmasa da geliştiricinin kendi ayağına sıkmaması için override ettiğini sandığı her metodun üstünde belirtmesi bu tip durumlarda "... must override or implement a supertype method" ve "1 quick fix available: remove @Override annotation" şeklinde IDE compileri tarafından verilen uyarıdan anlaşılacaktır.

Buraya kadar overrided ya da shadowed bir şekilde istediğimiz gibi alt sınıflarda da aynı isimde ve aynı metod imzasında değişken ve metodlar tanımlamış olabiliriz ve bu metodları da kullanırken herhangi bir yan etki ile karşılaşmamış olabiliriz. Bunun da sebebi nesne referanslarımızın sıkı sıkıya bağlı olmasından kaynaklıdır.

Aşağıdaki örnek kod dosyasında maskelenmiş bir değişkene nasıl erişildiği görülebilir. SpecialEmployee ve RegularEmployee tipinden referanslarla erişilen SpecialEmployee nesnesinde req referansı compile time için RegularEmployee sınıfının metodu olarak görünse de overriding mekanizması çalışmakta ve yine gerçek nesnenin metodunun işlevi yerine getirilmektedir. Ama poliformizim değişkenler için aynı şekilde çalışmamaktadır ve konsept devreye girer, shadowed değişken ortaya çıkarak temel sınıfa ait değişken değeri ekrana bastırılır.

Çıktı:
Multiplier: 0.03 variable a: 11
Multiplier: 0.03 variable a : 9

import java.math.BigDecimal;

class RegularEmployee {
int a = 9;
    private BigDecimal salary;

    public void setSalary(BigDecimal salary) {
        this.salary = salary;
    }

    public  BigDecimal getBonusMultiplier() {
        return new BigDecimal(".02");
    }

}

public class SpecialEmployee extends RegularEmployee {
int a = 11;
    @Override
public  BigDecimal getBonusMultiplier() {
        return new BigDecimal(".03");
    }
    
    public static void main(String args[])
    {
    SpecialEmployee spe = new SpecialEmployee();
    RegularEmployee req = new SpecialEmployee();
    System.out.println("Multiplier: " + spe.getBonusMultiplier() +" variable a: " + spe.a);
    System.out.println("Multiplier: "+req.getBonusMultiplier() +" variable a : " + req.a);
    
    }

}

Written on June 22, 2015