1. Konstruktorların aşırı yüklənməsinin sintaksisi
Həyatda nadir hallarda bütün obyektlər eyni qaydada yaradılır. Təsəvvür edin, Person (Insan) sinfi var. Bəzən bizə yalnız ad məlum olur. Bəzən — ad və yaş. Bəzən isə — heç nə bilmirik, hər şey susmaya görə olsun. İstifadəçini həmişə bütün parametrləri göstərməyə məcbur etmək, hətta onlar lazım deyilsə belə, qəribə olardı.
Konstruktorların aşırı yüklənməsi — sinif istifadəçisinə seçim vermək üsuludur: obyekti yaradarkən hansı parametrləri göstərmək, hansıları isə susmaya görə buraxmaq istədiyini özü müəyyən edir. Bu, sinfi çevik və istifadəyə rahat edir.
Analoqiya:
Konstruktor bürosunda avtomobillər yığılır. Kimsə baza komplektasiyanı sifariş edir (kondisionersiz, yalnız sükan və təkərlər), kimsə isə “lüks” istəyir (oturacaq isidilməsi, Wi‑Fi və maşının özü hərəkət etsin). Amma maşın — yenə də eyni sinifdir, sadəcə onu yığmağın fərqli yolları var!
Aşırı yükləmə — bu zaman bir sinifdə bir neçə konstruktor elan olunur, lakin parametrləri fərqlidir (parametrlərin sayı, tipi və ya sırası fərqlənir). Onların hamısının adı sinfin adı ilə eynidir və qaytarma tipi yoxdur.
Nümunə: Aşırı yüklənmiş konstruktorları olan sinif
public class Person {
String name;
int age;
// Parametrsiz konstruktor (susmaya görə)
public Person() {
this.name = "Naməlum";
this.age = 0;
}
// Bir parametrli konstruktor
public Person(String name) {
this.name = name;
this.age = 0;
}
// Iki parametrli konstruktor
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
İndi obyektləri müxtəlif üsullarla yarada bilərik:
Person p1 = new Person(); // ad = "Naməlum", yaş = 0
Person p2 = new Person("Vasya"); // ad = "Vasya", yaş = 0
Person p3 = new Person("Petya", 25); // ad = "Petya", yaş = 25
Java hansı konstruktoru istifadə edəcəyini necə anlayır?
Java, new sözündən sonra ötürdüyünüz arqumentlərin sayına və tiplərinə baxır. Əgər siz new Person("Vasya") yazırsınızsa, kompilyator bir String tipli parametrli konstruktoru axtarır. Əgər new Person("Petya", 25) yazırsınızsa, String və int parametrləri olan konstruktor lazımdır.
2. Bir konstruktordan digərini çağırmaq: this(...)
Bəzən konstruktorları aşırı yükləyərkən elə vəziyyət yaranır ki, kodun bir hissəsi təkrarlanır. Məsələn, istəyirsiniz ki, bütün konstruktorlar mütləq adı təyin etsin, yaş göstərilməyibsə, sıfıra bərabər olsun. Eyni məntiqi hər konstruktorda təkrarlamamaq üçün açar söz this(...) vasitəsilə bir konstruktordan digərini çağırmaq olar.
Nümunə
public class Person {
String name;
int age;
// Iki parametrli konstruktor
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// Bir parametrli konstruktor digərini çağırır
public Person(String name) {
this(name, 0); // Person(String name, int age) konstruktorunu çağırır
}
// Parametrsiz konstruktor digərini çağırır
public Person() {
this("Naməlum", 0);
}
}
public Person(String name) {
this(name, 0); // Person(String, int) konstruktorunu çağırır
}
Vacib qayda: this(...) vasitəsilə başqa konstruktorun çağırışı konstruktorda mütləq ilk sətir olmalıdır!
Nəyə görə bu lazımdır?
- Kodu təkrarlamağı azaldır.
- Ilkləndirmə məntiqini dəyişmək qərarına gəlsəniz (məsələn, susmaya görə dəyəri), bunu yalnız bir yerdə dəyişəcəksiniz.
- Kod daha səliqəli olur və onu dəstəkləmək asanlaşır.
3. Praktik nümunələr: real sinifdə aşırı yükləmə
Tutaq ki, bizdə Account sinfi var — bank hesabı. Bəzən yalnız sahibin adını bilirik, bəzən elə əvvəlcədən ilkin balansı göstərmək istəyirik, bəzən isə — hətta valyutanı da.
Aşırı yüklənmiş konstruktorları olan sinif nümunəsi
public class Account {
String owner;
double balance;
String currency;
// Üç parametrli konstruktor
public Account(String owner, double balance, String currency) {
this.owner = owner;
this.balance = balance;
this.currency = currency;
}
// Iki parametrli konstruktor (susmaya görə valyuta — "EUR")
public Account(String owner, double balance) {
this(owner, balance, "EUR");
}
// Bir parametrli konstruktor (balans = 0, valyuta = "EUR")
public Account(String owner) {
this(owner, 0.0, "EUR");
}
// Parametrsiz konstruktor (sahib — "Naməlum", balans = 0, valyuta = "EUR")
public Account() {
this("Naməlum", 0.0, "EUR");
}
public void printInfo() {
System.out.println(owner + ": " + balance + " " + currency);
}
}
İstifadə
public class Main {
public static void main(String[] args) {
Account acc1 = new Account("Ivan", 1000, "USD");
Account acc2 = new Account("Mariya", 500);
Account acc3 = new Account("Pyotr");
Account acc4 = new Account();
acc1.printInfo(); // Ivan: 1000.0 USD
acc2.printInfo(); // Mariya: 500.0 EUR
acc3.printInfo(); // Pyotr: 0.0 EUR
acc4.printInfo(); // Naməlum: 0.0 EUR
}
}
Niyə bu rahatdır?
- Obyektləri müxtəlif detallılıq səviyyəsində yaratmaq olar.
- Hər dəfə bütün parametrləri göstərməyə ehtiyac yoxdur (xüsusən də tez-tez eyni olduqda).
- Sinfi genişləndirmək asandır: yeni parametr yaranarsa, əlavə konstruktor da əlavə etmək olar.
4. Konstruktorların aşırı yüklənməsində tipik səhvlər
Səhv №1: Parametrlərin tipləri və sırası ilə qarışıqlıq.
Əgər sizdə iki konstruktor var — Person(String name, int age) və Person(int age, String name) — kompilyator onları fərqləndirəcək, amma sinifin istifadəçisi üçün bu, olduqca çaşdırıcı ola bilər. Belə hallardan qaçmaq daha yaxşıdır.
Səhv №2: Susmaya görə konstruktorun olmaması.
Əgər yalnız parametrləri olan konstruktorları elan etmisinizsə və sonra parametrsiz obyekt yaratmağa çalışsanız — kompilyasiya xətası alacaqsınız. Lazımdırsa, həmişə parametrsiz konstruktor əlavə edin.
Səhv №3: Başqa konstruktoru ilk sətrdə çağırmama cəhdi.
this(...) çağırışı həmişə konstruktorun ilk sətri olmalıdır. Əvvəlində nəsə yazsanız — kompilyasiya xətası olacaq.
Səhv №4: Konstruktor çağırışlarının döngəyə düşməsi.
Əgər konstruktor özü‑özünü (birbaşa və ya zəncirlə) çağırırsa, sonsuz rekursiya səbəbindən kompilyasiya xətası baş verəcək.
Səhv №5: Ilkləndirilməmiş sahələr.
Hər hansı sahəni konstruktorda (və ya çağırış zəncirində) ilkləndirməyi unutmusunuzsa, obyekt yalnış vəziyyətdə qala bilər. Obyekt yaradıldıqdan sonra bütün sahələrin məntiqli dəyərlərə malik olduğunu yoxlayın.
GO TO FULL VERSION