JavaRush /Java Blogu /Random-AZ /Java-da konstruktorlar

Java-da konstruktorlar

Qrupda dərc edilmişdir
Salam! Bu gün biz obyektlərimizə aid çox vacib bir mövzuya baxacağıq. Burada mübaliğəsiz deyə bilərik ki, siz bu biliklərdən hər gün real işdə istifadə edəcəksiniz! Konstruktorlar haqqında danışacağıq. Bu termini ilk dəfədir eşidirsiniz, amma əslində konstruktorlardan istifadə etmisiniz, ancaq özünüz fərqinə varmadınız :) Bunu sonra görəcəyik.

Java-da konstruktor nədir və nə üçün lazımdır?

Gəlin iki misala baxaq.
public class Car {

   String model;
   int maxSpeed;

   public static void main(String[] args) {

       Car bugatti = new Car();
       bugatti.model = "Bugatti Veyron";
       bugatti.maxSpeed = 407;

   }
}
Avtomobilimizi yaratdıq və onun modelini və maksimum sürətini təyin etdik. Bununla belə, real layihədə Avtomobil obyekti açıq şəkildə 2-dən çox sahəyə sahib olacaqdır. Və, məsələn, 16 sahə!
public class Car {

   String model;//model
   int maxSpeed;//max speed
   int wheels;// disk width
   double engineVolume;//engine capacity
   String color;//color
   int yearOfIssue;//year of issue
   String ownerFirstName;//Owner's name
   String ownerLastName;//owner's last name
   long price;//price
   boolean isNew;//new or not
   int placesInTheSalon;//number of seats in the cabin
   String salonMaterial;// interior material
   boolean insurance;//is it insured
   String manufacturerCountry;//manufacturer country
   int trunkVolume;// trunk volume
   int accelerationTo100km;//acceleration to 100 km/h in seconds


   public static void main(String[] args) {
       Car bugatti = new Car();

       bugatti.color = "blue";
       bugatti.accelerationTo100km = 3;
       bugatti.engineVolume = 6.3;
       bugatti.manufacturerCountry = "Italy";
       bugatti.ownerFirstName = "Amigo";
       bugatti.yearOfIssue = 2016;
       bugatti.insurance = true;
       bugatti.price = 2000000;
       bugatti.isNew = false;
       bugatti.placesInTheSalon = 2;
       bugatti.maxSpeed = 407;
       bugatti.model = "Bugatti Veyron";

   }

}
Biz yeni Avtomobil obyekti yaratdıq . Bir problem: 16 sahəmiz var, lakin biz yalnız 12-ni işə saldıq ! Unudduqlarımızı tapmaq üçün kodu istifadə edərək indi cəhd edin! O qədər də asan deyil, elə deyilmi? Belə bir vəziyyətdə proqramçı asanlıqla səhv edə bilər və bəzi sahənin başlanğıcını atlaya bilər. Nəticədə, proqram davranışı səhv olacaq:
public class Car {

   String model;//model
   int maxSpeed;//max speed
   int wheels;// disk width
   double engineVolume;//engine capacity
   String color;//color
   int yearOfIssue;//year of issue
   String ownerFirstName;//Owner's name
   String ownerLastName;//owner's last name
   long price;//price
   boolean isNew;//new or not
   int placesInTheSalon;//number of seats in the cabin
   String salonMaterial;// interior material
   boolean insurance;//is it insured
   String manufacturerCountry;//manufacturer country
   int trunkVolume;// trunk volume
   int accelerationTo100km;//acceleration to 100 km/h in seconds


   public static void main(String[] args) {
       Car bugatti = new Car();

       bugatti.color = "blue";
       bugatti.accelerationTo100km = 3;
       bugatti.engineVolume = 6.3;
       bugatti.manufacturerCountry = "Italy";
       bugatti.ownerFirstName = "Amigo";
       bugatti.yearOfIssue = 2016;
       bugatti.insurance = true;
       bugatti.price = 2000000;
       bugatti.isNew = false;
       bugatti.placesInTheSalon = 2;
       bugatti.maxSpeed = 407;
       bugatti.model = "Bugatti Veyron";

       System.out.println("Model Bugatti Veyron. Engine size - " + bugatti.engineVolume + ", trunk - " + bugatti.trunkVolume + ", salon is made of" + bugatti.salonMaterial +
       ", disc width - " + bugatti.wheels + ". Was acquired in 2018 by Mr. " + bugatti.ownerLastName);

   }

}
Konsol çıxışı:
Bugatti Veyron modeli. Mühərrikin yerdəyişməsi - 6.3, baqaj - 0, salon null, halqa eni - 0. 2018-ci ildə cənab null tərəfindən alınıb
Maşına 2 milyon dollar ödəmiş alıcınız “Cənab Null” adlandırılmağın xoşuna gəlməyəcək! Amma ciddi şəkildə, sonda proqramımız səhv yaradılmış obyektlə başa çatdı - halqasının eni 0 olan avtomobil (yəni heç bir təkər yoxdur), itkin baqaj, naməlum materialdan hazırlanmış salon və hətta naməlum bir şəxsə məxsus bir avtomobil. . Proqram işləyərkən belə bir səhvin necə baş verə biləcəyini yalnız təsəvvür etmək olar! Bu cür halların qarşısını hansısa yolla almalıyıq. Proqramımızın bir məhdudiyyətə sahib olması lazımdır: yeni bir avtomobil obyekti yaratarkən, məsələn, onun üçün model və maksimum sürət həmişə göstərilməlidir. Əks halda, obyektin yaradılmasına icazə verməyin. Konstruktor funksiyaları bu vəzifənin öhdəsindən asanlıqla gəlir. Adlarını bir səbəbə görə aldılar. Konstruktor sinifin hər bir yeni obyektinin uyğun gəlməli olduğu bir növ "skelet" yaradır. Rahatlıq üçün iki sahə ilə Car sinifinin daha sadə versiyasına qayıdaq . Tələblərimizi nəzərə alaraq, Avtomobil sinfi üçün konstruktor belə görünəcək:
public Car(String model, int maxSpeed) {
   this.model = model;
   this.maxSpeed = maxSpeed;
}
Və obyekt yaratmaq indi belə görünür:
public static void main(String[] args) {
   Car bugatti = new Car("Bugatti Veyron", 407);
}
Diqqət yetirinkonstruktor necə yaradılır. Adi metoda bənzəyir, lakin onun qaytarma növü yoxdur. Bu halda, sinif adı konstruktorda, həmçinin böyük hərflə göstərilir. Bizim vəziyyətimizdə - Avtomobil . Bundan əlavə, konstruktor new-to-you açar sözündən istifadə edir this . "this" ingilis dilində "bu, bu" deməkdir. Bu söz müəyyən bir obyektə aiddir. Konstruktorda kod:
public Car(String model, int maxSpeed) {
   this.model = model;
   this.maxSpeed = maxSpeed;
}
demək olar ki, hərfi tərcümə edilə bilər: " bu maşın üçün model (indi yaradırıq) = konstruktorda göstərilən model arqumenti . Bu maşın üçün maxSpeed ​​(bizim yaratdığımız) = maxSpeed ​​arqumenti , hansı konstruktorda göstərilmişdir." Bu baş verdi:
public class Car {

   String model;
   int maxSpeed;

   public Car(String model, int maxSpeed) {
       this.model = model;
       this.maxSpeed = maxSpeed;
   }

   public static void main(String[] args) {
       Car bugatti = new Car("Bugatti Veyron", 407);
       System.out.println(bugatti.model);
       System.out.println(bugatti.maxSpeed);
   }

}
Konsol çıxışı:
Bugatti Veyron 407
Konstruktor tələb olunan dəyərləri uğurla təyin etdi. Konstruktorun adi metoda çox bənzədiyini görmüsünüz! Bu belədir: konstruktor bir metoddur, yalnız bir az spesifik :) Metodda olduğu kimi parametrləri konstruktorumuza ötürdük. Və metodu çağırmaq kimi, konstruktoru çağırmaq da onları təyin etməsəniz işləməyəcək:
public class Car {

   String model;
   int maxSpeed;

   public Car(String model, int maxSpeed) {
       this.model = model;
       this.maxSpeed = maxSpeed;
   }

   public static void main(String[] args) {
       Car bugatti = new Car(); //error!
   }

}
Görürsünüz, dizayner bizim nail olmağa çalışdığımız şeyi etdi. İndi nə sürətsiz, nə də modelsiz avtomobil yarada bilməzsiniz! Konstruktorlar və metodlar arasındakı oxşarlıqlar bununla bitmir. Metodlar kimi konstruktorlar da həddən artıq yüklənə bilər. Təsəvvür edin ki, evdə 2 pişik var. Onlardan birini pişik balası kimi götürdünüz, ikincisini isə böyüklər kimi küçədən evə gətirdiniz və onun neçə yaşında olduğunu dəqiq bilmirsiniz. Bu o deməkdir ki, proqramımız iki növ pişik yarada bilməlidir - birinci pişik üçün ad və yaş, ikinci pişik üçün isə yalnız ad ilə. Bunu etmək üçün konstruktoru həddən artıq yükləyəcəyik:
public class Cat {

   String name;
   int age;

   //for the first cat
   public Cat(String name, int age) {
       this.name = name;
       this.age = age;
   }

   //for the second cat
   public Cat(String name) {
       this.name = name;
   }

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5);
       Cat streetCatNamedBob = new Cat("Bob");
   }

}
"Ad" və "yaş" parametrləri ilə orijinal konstruktora başqa bir ad əlavə etdik. Metodları əvvəlki dərslərdə də eyni şəkildə həddən artıq yükləmişdik. İndi biz pişiklərin hər iki versiyasını uğurla yarada bilərik :) Konstruktorlar niyə lazımdır?  - 2Yadınızdadırmı, mühazirənin əvvəlində demişdik ki, siz artıq konstruktorlardan istifadə etmisiniz, ancaq bunu hiss etməmisiniz? Bu doğrudur. Məsələ burasındadır ki, Java-da hər bir sinifin standart konstruktoru var. Onun heç bir arqumenti yoxdur, lakin hər hansı bir sinfin hər hansı obyekti yaradılanda o, işə düşür.
public class Cat {

   public static void main(String[] args) {

       Cat barsik = new Cat(); //this is where the default constructor worked
   }
}
İlk baxışdan bu nəzərə çarpmır. Yaxşı, biz bir obyekt yaratdıq və onu yaratdıq, dizaynerin işi haradadır? Bunu görmək üçün gəlin öz əlimizlə Cat sinfi üçün boş konstruktor yazaq və onun içərisində konsola bəzi ifadələr çap edəcəyik. Göstərilirsə, konstruktor işləmişdir.
public class Cat {

   public Cat() {
       System.out.println("Created a cat!");
   }

   public static void main(String[] args) {

       Cat barsik = new Cat(); //this is where the default constructor worked
   }
}
Konsol çıxışı:
Bir pişik yaratdılar!
Budur təsdiq! Standart konstruktor həmişə siniflərinizdə görünməz şəkildə mövcuddur. Ancaq bunun daha bir xüsusiyyətini bilmək lazımdır. Arqumentlərlə bəzi konstruktor yaratdığınız zaman standart konstruktor sinifdən yox olur. Bunun sübutunu, əslində, yuxarıda gördük. Bu kodda:
public class Cat {

   String name;
   int age;

   public Cat(String name, int age) {
       this.name = name;
       this.age = age;
   }

   public static void main(String[] args) {

       Cat barsik = new Cat(); //error!
   }
}
Cat : string + number üçün konstruktor təyin etdiyimiz üçün adı və yaşı olmayan pişik yarada bilmədik . Defolt konstruktor bundan dərhal sonra sinifdən itdi. Buna görə də, yadda saxlamağınızdan əmin olun: sinifinizdə boş olan da daxil olmaqla bir neçə konstruktor lazımdırsa, onu ayrıca yaratmalısınız. Məsələn, biz baytarlıq klinikası üçün proqram yaradırıq. Klinikamız adlarını və yaşlarını bilmədiyimiz evsiz pişiklərə xeyirxah işlər görmək, onlara kömək etmək istəyir. Sonra kodumuz belə görünməlidir:
public class Cat {

   String name;
   int age;

   //for domestic cats
   public Cat(String name, int age) {
       this.name = name;
       this.age = age;
   }

   //for street cats
   public Cat() {
   }

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5);
       Cat streetCat = new Cat();
   }
}
İndi biz açıq şəkildə defolt konstruktor yazmışıq, biz hər iki tipdə pişik yarada bilərik :) Konstruktor üçün (hər hansı bir metodda olduğu kimi) arqumentlərin sırası çox vacibdir. Konstruktorumuzda ad və yaş arqumentlərini dəyişdirək.
public class Cat {

   String name;
   int age;

   public Cat(int age, String name) {
       this.name = name;
       this.age = age;
   }

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 10); //error!
   }
}
Xəta! Konstruktor açıq şəkildə bildirir ki, Cat obyekti yaradılanda ona həmin ardıcıllıqla nömrə və sətir ötürülməlidir. Buna görə kodumuz işləmir. Bunu xatırladığınızdan və öz dərslərinizi yaradan zaman bunu nəzərə aldığınızdan əmin olun:
public Cat(String name, int age) {
   this.name = name;
   this.age = age;
}

public Cat(int age, String name) {
   this.age = age;
   this.name = name;
}
Bunlar tamamilə fərqli iki dizaynerdir! “Bizə konstruktor nə üçün lazımdır?” sualının cavabını bir cümlə ilə ifadə etsək, belə deyə bilərik: obyektlər həmişə düzgün vəziyyətdə olsun. Konstruktorlardan istifadə etdiyiniz zaman bütün dəyişənləriniz düzgün işə salınacaq və proqramda sürəti 0 olan avtomobillər və ya digər “yanlış” obyektlər olmayacaq. Onların istifadəsi, ilk növbədə, proqramçının özü üçün çox faydalıdır. Sahələri özünüz işə salsanız, nəyisə əldən vermək və səhv etmək riski yüksəkdir. Ancaq konstruktorla bu baş verməyəcək: bütün lazımi arqumentləri ona ötürməmisinizsə və ya onların növlərini qarışdırmısınızsa, kompilyator dərhal xəta atacaq. Ayrılıqda qeyd etmək lazımdır ki, konstruktorun içərisinə proqramınızın məntiqini qoymamalısınız. Bunu etmək üçün sizə lazım olan bütün funksionallığı təsvir edə biləcəyiniz üsullarınız var. Konstruktor məntiqinin niyə pis fikir olduğuna baxaq:
public class CarFactory {

   String name;
   int age;
   int carsCount;

   public CarFactory(String name, int age, int carsCount) {
   this.name = name;
   this.age = age;
   this.carsCount = carsCount;

   System.out.println("Our car factory is called" + this.name);
   System.out.println("She was founded" + this.age + " years ago" );
   System.out.println("During this time it was produced" + this.carsCount +  "cars");
   System.out.println("On average she produces" + (this.carsCount/this.age) + "cars per year");
}

   public static void main(String[] args) {

       CarFactory ford = new CarFactory("Ford", 115 , 50000000);
   }
}
Avtomobil istehsal edən zavodu təsvir edən CarFactory sinifimiz var . Konstruktor daxilində biz bütün sahələri inisiallaşdırırıq və məntiqi bura yerləşdiririk: biz konsola zavod haqqında bəzi məlumatları göstəririk. Görünür ki, bunda səhv bir şey yoxdur, proqram mükəmməl işləmişdir. Konsol çıxışı:
Bizim avtomobil zavodumuz Ford adlanır.115 il əvvəl yaranıb.Bu müddət ərzində 50000000 avtomobil istehsal edib.Orta hesabla ildə 434782 avtomobil istehsal olunur.
Amma əslində biz saatlı bomba yerləşdirmişik. Və belə kod çox asanlıqla səhvlərə səbəb ola bilər. Təsəvvür edək ki, indi söhbət Forddan yox, bir ildən az müddətdə mövcud olan və 1000 avtomobil istehsal edən yeni “Amigo Motors” zavodundan gedir:
public class CarFactory {

   String name;
   int age;
   int carsCount;

   public CarFactory(String name, int age, int carsCount) {
   this.name = name;
   this.age = age;
   this.carsCount = carsCount;

   System.out.println("Our car factory is called" + this.name);
   System.out.println("She was founded" + this.age + " years ago" );
   System.out.println("During this time it was produced" + this.carsCount +  "cars");
   System.out.println("On average she produces" + (this.carsCount/this.age) + "cars per year");
}


   public static void main(String[] args) {

       CarFactory ford = new CarFactory("Amigo Motors", 0 , 1000);
   }
}
Konsol çıxışı:
Bizim avtomobil zavodumuz "main" java.lang.ArithmeticException mövzusunda Amigo Motors Exception adlanır: / by zero O, 0 il əvvəl təsis edilib Bu müddət ərzində o, CarFactory-də 1000 avtomobil istehsal edib.<init>(CarFactory.java:15) at CarFactory.main(CarFactory.java:23) Çıxış kodu 1</init> ilə proses tamamlandı
Biz gəldik! Proqram qəribə bir səhvlə başa çatdı. Səbəbin nə olduğunu təxmin etməyə çalışacaqsınız? Səbəb konstruktorda yerləşdirdiyimiz məntiqdir. Xüsusilə, bu sətirdə:
System.out.println("On average she produces" + (this.carsCount/this.age) + "cars per year");
Burada hesablama aparırıq və istehsal olunan avtomobillərin sayını zavodun yaşına bölürük. Fabrikimiz yeni olduğu üçün (yəni 0 ildir) nəticədə riyaziyyatda qadağan olunan 0-a bölünür. Nəticədə proqram xəta ilə dayandırılır. Nə etməliydik? Bütün məntiqi ayrı bir metoda köçürün və onu çağırın, məsələn, printFactoryInfo() . Siz onu parametr kimi CarFactory obyektini ötürə bilərsiniz . Siz həmçinin bütün məntiqi oraya qoya bilərsiniz və eyni zamanda - sıfır illərlə bizimki kimi mümkün səhvləri emal edə bilərsiniz. Hər kəsə öz. Konstruktorlar obyektin vəziyyətini düzgün təyin etmək üçün lazımdır. Biznes məntiqi üçün üsullarımız var. Birini digəri ilə qarışdırmamalısınız.
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION