CodeGym /Kurslar /JAVA 25 SELF /Metodların yenidən təyin edilməsi (override), @Override a...

Metodların yenidən təyin edilməsi (override), @Override annotasiyası

JAVA 25 SELF
Səviyyə , Dərs
Mövcuddur

1. Metodun yenidən təyin edilməsi

Həyatda tez-tez «varis» xüsusi davranır. Məsələn, bütün heyvanlar səs çıxarır, amma pişik — «miyau», it — «hav-hav», proqramçı isə — «ay, yenə bug!». Proqramlaşdırmada bu, metodun yenidən təyin edilməsi (override) vasitəsilə reallaşır.

Metodun yenidən təyin edilməsi — alt sinifin valideyn sinifdə artıq elan olunmuş metodu üçün öz reallaşdırmasını təqdim etməsidir. Yəni standart davranışı daha spesifik olan öz davranışı ilə «əvəzləyir».

Analoji. Valideyn sinfi «borş» üçün brend resept kimi təsəvvür etsək, metodun yenidən təyin edilməsi — nənənin ora öz gizli inqrediyentini əlavə etməsidir. Borş borş olaraq qalır, amma hərəsinin dadı özünəməxsusdur.

Metodu yenidən təyin etmək üçün törəmə sinifdə valideyndəki ilə tam eyni siqnaturaya (ad, parametrlər, qaytarılan tip) malik metod elan etmək lazımdır.

Nümunə: heyvanlar və səsləri

class Animal {
    void makeSound() {
        System.out.println("Some generic animal sound");
    }
}

class Dog extends Animal {
    // makeSound() metodunu yenidən təyin edirik
    void makeSound() {
        System.out.println("Woof!");
    }
}

class Cat extends Animal {
    // makeSound() metodunu yenidən təyin edirik
    void makeSound() {
        System.out.println("Meow!");
    }
}

İndi əgər Dog obyektini yaradıb makeSound() çağırsanız, "Woof!" eşidəcəksiniz, "Some generic animal sound" yox.

Kodda nümayiş

public class Main {
    public static void main(String[] args) {
        Animal generic = new Animal();
        Dog dog = new Dog();
        Cat cat = new Cat();

        generic.makeSound(); // Some generic animal sound
        dog.makeSound();     // Woof!
        cat.makeSound();     // Meow!
    }
}

Vacibdir: əgər törəmədə eyni siqnaturalı metod yoxdursa, valideynin metodu istifadə olunacaq.

2. @Override annotasiyası: nə üçün lazımdır və necə istifadə olunur

Java-da yenidən təyin edilmiş metodları xüsusi @Override annotasiyası ilə qeyd etmək qəbul olunub. Bu, sadəcə kod üçün bəzək deyil, faydalı alətdir:

  • Kompilyator yoxlayır ki, həqiqətən valideyn metodunu yenidən təyin edirsiniz. Əgər addan, parametr tipindən və ya qaytarılan tipdən yanlsanız — kompilyator xəta verəcək.
  • Kodun oxunaqlılığını artırır. Başqa bir proqramçı dərhal görür: «Aha, bu metod valideyn metodunu yenidən təyin edir».

@Override ilə nümunə

class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("Woof!");
    }
}

Əgər təsadüfən metodda void makeSond() (yazılış xətası!) yazsanız və metod @Override ilə işarələnibsə, kompilyator xəbərdarlıq edəcək: "Method does not override or implement a method from a supertype".

Müasir standartlar. @Override istifadə etmək yaxşı praktikadır və sənaye standartıdır. Kompilyator tələb etməsə belə, həmişə bu annotasiyanı qoyun — həm özünüz, həm də həmkarlarınız üçün işi asanlaşdıracaq.

3. Yenidən təyin edilmiş metodun çağırışı necə işləyir

Törəmə obyekt üzərində metod çağırdıqda, hətta dəyişən valideyn tipi kimi elan edilsə belə, törəmənin reallaşdırması işləyəcək.

Nümunə: polimorfizm iş başında

Animal animal = new Dog();
animal.makeSound(); // "Woof!", "Some generic animal sound" deyil

Burada dəyişənin tipi Animal-dır, amma əslində içində Dog obyekti var. Java «başa düşür» ki, Dog-dakı yenidən təyin edilmiş metodu çağırmaq lazımdır. Bu, polimorfizmdir (ətraflı — növbəti mühazirələrdə).

4. Yenidən təyin etmənin məhdudiyyətləri və qaydaları

Metodun siqnaturası

  • Ad, tip və parametrlərin sırası valideyndəki metodla üst-üstə düşməlidir.
  • Qaytarılan tip eyni olmalı və ya kovariant (valideynin qaytardığı tipin alt tipi) olmalıdır. Məsələn, valideyn Animal qaytarırsa, törəmə Dog qaytara bilər — bu, icazəlidir.

Giriş modifikatorları

  • Girişi valideyndən daha sərt etmək olmaz.
  • Əgər valideyn metodu public-dirsə, yenidən təyin edilmiş metod da public olmalıdır.
  • Əgər valideyn protected-dirsə, yenidən təyin edilmiş metod protected və ya public ola bilər.

Əksini etməyə çalışsanız, kompilyator deyəcək: "Cannot reduce the visibility of the inherited method".

İstisnalar

  • Yenidən təyin edilmiş metod valideyndəki elanında olmayan yeni checked‑istisna ata bilməz.
  • Valideyndən daha az istisna və ya onların alt tiplərini ata bilərsiniz.

static, final, private

  • staticfinal kimi elan olunmuş, həmçinin private metodları yenidən təyin etmək olmaz.
  • static — bu, yenidən təyin etmə deyil, gizlətmədir (hiding).
  • final — ümumiyyətlə yenidən təyin edilə bilməz, Java belə metodları qoruyur.
  • private — törəmə sinifdə görünmür, yenidən təyin edilə bilməz (yalnız eyni adlı yeni metod elan edə bilərsiniz).

Konstruktorlar

Konstruktorlar miras alınmır və yenidən təyin edilmir. Hər sinifin öz konstruktorları var.

5. «Zoopark» tədris tətbiqini inkişaf etdiririk

Artıq nəzəriyyəni praktikada tətbiq etməyin vaxtıdır! Gəlin «Zoopark» tətbiqimizi inkişaf etdirməyə davam edək.

Addım 1. Baza sinif Animal

public class Animal {
    public void makeSound() {
        System.out.println("Some generic animal sound");
    }

    public void sleep() {
        System.out.println("Zzz...");
    }
}

Addım 2. Törəmə siniflər DogCat

public class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof!");
    }

    // Yalnız Dog üçün əlavə metod
    public void fetch() {
        System.out.println("Dog brings the stick!");
    }
}

public class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Meow!");
    }

    // Yalnız Cat üçün əlavə metod
    public void scratch() {
        System.out.println("Cat scratches the sofa!");
    }
}

Addım 3. Yenidən təyin etməni tətbiq edirik

public class ZooTest {
    public static void main(String[] args) {
        Animal generic = new Animal();
        Animal dog = new Dog();
        Animal cat = new Cat();

        generic.makeSound(); // Some generic animal sound
        dog.makeSound();     // Woof!
        cat.makeSound();     // Meow!

        // dog.fetch(); // Xəta! Animal tipli dəyişən fetch() barədə bilmir
        // cat.scratch(); // Eynidir

        // Amma tip açıq şəkildə göstərilsə:
        if (dog instanceof Dog) {
            ((Dog) dog).fetch(); // Dog brings the stick!
        }
        if (cat instanceof Cat) {
            ((Cat) cat).scratch(); // Cat scratches the sofa!
        }
    }
}

Şərh:
makeSound() metodu polimorf işləyir — obyektin real sinfindəki versiya çağırılır. Amma spesifik metodlar (fetch, scratch) yalnız açıq tip çevrilməsi ilə əlçatandır — bu, irsiyyət və yenidən təyin etmənin necə işlədiyini anlamaq üçün vacibdir.

6. Qaytarılan tiplə nümunə (kovariantlıq)

Bəzən istəyirik ki, yenidən təyin edilmiş metod daha «dar» tip qaytarsın. Məsələn:

class Animal {
    Animal getFriend() {
        return new Animal();
    }
}

class Dog extends Animal {
    @Override
    Dog getFriend() { // Qaytarılan tip — Dog, Animal-ın alt tipidir
        return new Dog();
    }
}

Bu, qaytarılan tipin kovariantlığı adlanır və Java-da (Java 5-dən başlayaraq) icazəlidir.

7. @Override istifadə etməsəniz nə olar?

Əgər təsadüfən metod adında və ya parametrlərdə səhv etsəniz və @Override annotasiyası olmasa, Java xəbərdarlıq etməyəcək. Nəticədə, yenidən təyin etməyəcək, yeni metod yaradacaqsınız və gözlənilən davranış dəyişməyəcək.

Səhv nümunəsi

class Dog extends Animal {
    // Yazılış xətası: makeSound əvəzinə makeSoud
    void makeSoud() {
        System.out.println("Woof!");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog();
        dog.makeSound(); // "Some generic animal sound" çap olunacaq
    }
}

Əgər @Override olsaydı, kompilyator xəta verərdi: "Method does not override or implement a method from a supertype".

8. Metodları yenidən təyin edərkən tipik səhvlər

Səhv №1: @Override annotasiyasının olmaması.
Onsuz ad və ya parametrlərdə asanlıqla səhv etmək olar. Nəticədə metod yenidən təyin edilməyəcək və proqram gözlədiyiniz kimi davranmayacaq.

Səhv №2: giriş modifikatorunu daraltmaq cəhdi.
Əgər valideyn metodu public-dirsə, siz protected və ya private yazsanız — kompilyasiya xətası alacaqsınız.

Səhv №3: siqnaturanın uyğun gəlməməsi.
Parametrlər heç olmasa tip üzrə fərqlənirsə — bu, artıq yenidən təyin etmə deyil, yükləmədir (overloading).

Səhv №4: final və ya static metodu yenidən təyin etməyə cəhd.
Java buna icazə vermir: final yenidən təyin etmədən qoruyur, static metodlar isə ümumiyyətlə yenidən təyin olunmur (yalnız gizlədilir).

Səhv №5: qaytarılan tipin uyğun olmayan tipə dəyişdirilməsi.
Yalnız valideynin qaytardığı tipin alt tipini (kovariantlıq) qaytarmaq olar, tamamilə başqa tipi yox.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION