JavaRush /Java Blog /Random-TK /Localerli usulda içerki sapaklar

Localerli usulda içerki sapaklar

Toparda çap edildi
Salam! Geliň, başga bir görnüşli synp hakda gürleşeliň. Localerli synplar hakda (Methoderli içki synplaryň usuly). Okuwdan ozal ýatda saklamaly zadyňyz, olaryň höwürtgelenen synplaryň gurluşyndaky orny. Diagrammamyza esaslanyp, ýerli synplaryň içerki synplaryň bir görnüşidigine düşünip bileris, öňki materiallaryň birindeMethoderli usulda içerki sapaklar - 2 jikme-jik gürleşipdik . Şeýle-de bolsa, ýerli synplarda içerki synplardan birnäçe möhüm aýratynlyklar we tapawutlar bar. Esasy zat olaryň beýanynda: classerli synp diňe kod blokynda yglan edilýär. Köplenç - daşarky synpyň käbir usulynyň içinde. Mysal üçin, şeýle bolup biler:
public class PhoneNumberValidator {

   public void validatePhoneNumber(String number) {

        class PhoneNumber {

           private String phoneNumber;

           public PhoneNumber() {
               this.phoneNumber = number;
           }

           public String getPhoneNumber() {
               return phoneNumber;
           }

           public void setPhoneNumber(String phoneNumber) {
               this.phoneNumber = phoneNumber;
           }
       }

       //...code валидации номера
   }
}
Möhüm!Java 7 gurlan bolsaňyz, bu kod IDEA-da goýlanda düzülmez. Leksiýanyň ahyrynda munuň sebäpleri barada gürleşeris. Birnäçe söz bilen aýdylanda, ýerli synplaryň işi dil görnüşine gaty baglydyr. Bu kod siziň üçin düzülmese, IDEA-daky dil wersiýasyny Java 8-e geçirip bilersiňiz ýa-da finalusul görnüşine parametr ýaly bir söz goşup bilersiňiz : validatePhoneNumber(final String number). Ondan soň hemme zat işlär. Bu kiçijik programma - telefon belgisini tassyklaýjy. Usuly validatePhoneNumber()giriş hökmünde bir setir alýar we telefon belgidigini ýa-da ýokdugyny kesgitleýär. Bu usulyň içinde ýerli synpymyzy yglan etdik PhoneNumber. Mantykly soragyňyz bolup biler: näme üçin? Näme üçin usulyň içinde synp yglan etmeli? Näme üçin adaty içki synpy ulanmaly däl? Hakykatdanam, muny edip bolar: synpy PhoneNumberiçerki etmek. Anotherene bir zat, gutarnykly karar programmaňyzyň gurluşyna we maksadyna baglydyr. Içki synplar baradaky leksiýadan mysalymyzy ýada salalyň:
public class Bicycle {

   private String model;
   private int mawWeight;

   public Bicycle(String model, int mawWeight) {
       this.model = model;
       this.mawWeight = mawWeight;
   }

   public void start() {
       System.out.println("Go!");
   }

   public class HandleBar {

       public void right() {
           System.out.println("Steering wheel to the right!");
       }

       public void left() {

           System.out.println("Steering wheel to the left!");
       }
   }
}
HandleBarOnda (tutawaçlar) welosipediň içerki synpyny ýasadyk . Tapawudy näme? Ilki bilen synpy ulanmakda. HandleBarIkinji mysaldan synp, PhoneNumberbirinjisinden has çylşyrymly bir zat. Birinjiden, y-da HandleBarköpçülige açyk usullar bar rightwe left(kesgitleýji däl). Ikinjiden, nirä we onuň daşarky synpyna mätäçligimizi öňünden çaklap bilmeris Bicycle- bu bir programmanyň içinde-de onlarça dürli ýer we usul bolup biler. Emma synp bilen PhoneNumberhemme zat has ýönekeý. Maksatnamamyz gaty ýönekeý. Diňe bir wezipesi bar - belginiň telefon belgidigini ýa-da ýokdugyny barlamak. Köplenç biziňkiler PhoneNumberValidatorhatda garaşsyz programma bolman, diňe esasy programma üçin ygtyýar logikasynyň bir bölegi bolar. Mysal üçin, dürli web sahypalarynda, hasaba alnanda, köplenç telefon belgisini girizmek soralýar. Sanlaryň ýerine käbir bolgusyz zatlar ýazsaňyz, sahypa ýalňyşlyk görkezer: "Bu telefon belgisi däl!" Şeýle sahypanyň işlemegi üçin (has dogrusy, ulanyjynyň ygtyýarlandyryş mehanizmi) ony döredijiler kodda biziň meňzeşimizi goşup bilerler PhoneNumberValidator. Başgaça aýdylanda, programmada bir ýerde we başga hiç ýerde ulanyljak bir usul bilen bir daşarky synpymyz bar. Şeýle bolsa, onda hiç zat üýtgemez: bir usul öz işini ýerine ýetirýär - bu hemmesi. Bu ýagdaýda ähli iş logikasy bir usulda toplanylandygy sebäpli, ol ýerde goşmaça synpy jemlemek has amatly we dogry bolar. Getter we sazlaýjydan başga öz usullary ýok. Aslynda diňe ondan konstruktor maglumatlary gerek. Başga usullarda ulanylmaýar. Şonuň üçin bu hakda ulanylýan ýeke-täk usuldan daşgary maglumat ýaýratmaga esas ýok. Usulda ýerli synpy yglan etmegiň mysalyny berdik, ýöne bu ýeke-täk mümkinçilik däl. Diňe kod blokynda yglan edip bolar:
public class PhoneNumberValidator {

   {
       class PhoneNumber {

           private String phoneNumber;

           public PhoneNumber(String phoneNumber) {
               this.phoneNumber = phoneNumber;
           }
       }

   }

   public void validatePhoneNumber(String phoneNumber) {


       //...code валидации номера
   }
}
Evena-da bir aýlawda for!
public class PhoneNumberValidator {


   public void validatePhoneNumber(String phoneNumber) {

       for (int i = 0; i < 10; i++) {

           class PhoneNumber {

               private String phoneNumber;

               public PhoneNumber(String phoneNumber) {
                   this.phoneNumber = phoneNumber;
               }
           }

           //...Howая-то логика
       }

       //...code валидации номера
   }
}
Emma beýle ýagdaýlar gaty seýrek. Köp halatlarda beýannama henizem usulyň içinde bolar. Şeýlelik bilen, bildiriş bilen iş salyşdyk, “pelsepe” hakda-da gürleşdik :) Içerki synplardan ýerli synplardan başga haýsy aýratynlyklar we tapawutlar bar? Classerli synp obýekti yglan edilen usuldan ýa-da blokdan daşarda döredilip bilinmez. generatePhoneNumber()Tötänleýin telefon belgisini döredýän we a gaýtarýan usul gerekdigini göz öňüne getiriň PhoneNumber. Häzirki ýagdaýda tassyklaýjy synpymyzda beýle usuly döredip bilmeris:
public class PhoneNumberValidator {

   public void validatePhoneNumber(String number) {

        class PhoneNumber {

           private String phoneNumber;

           public PhoneNumber() {
               this.phoneNumber = number;
           }

           public String getPhoneNumber() {
               return phoneNumber;
           }

           public void setPhoneNumber(String phoneNumber) {
               this.phoneNumber = phoneNumber;
           }
       }

       //...code валидации номера
   }

   //ошибка! компилятор не понимает, что это за класс - PhoneNumber
   public PhoneNumber generatePhoneNumber() {

   }

}
Classeserli synplaryň ýene bir möhüm aýratynlygy ýerli üýtgeýänlere we usul parametrlerine girmek ukybydyr. Forgetatdan çykaran bolsaňyz, “ýerli” usulyň içinde yglan edilen üýtgeýjidir. .Agny, käbir maksatlarymyz üçin String russianCountryCodeusulyň içinde ýerli üýtgeýjini döretsek validatePhoneNumber(), oňa ýerli synpdan girip bileris PhoneNumber. Şeýle-de bolsa, bu ýerde programmada ulanylýan diliň wersiýasyna bagly köp inçelikler bar. Leksiýanyň başynda mysallaryň birindäki kodyň Java 7-de jemlenip bilmejekdigini belledik, ýadyňyzdamy? Indi munuň sebäplerine seredeliň :) Java 7-de ýerli synp diňe ýerli üýtgeýän ýa-da usul parametrine usulda yglan edilse girip biler final:
public void validatePhoneNumber(String number) {

   String russianCountryCode = "+7";

   class PhoneNumber {

       private String phoneNumber;

       //ошибка! параметр метода должен быть объявлен How final!
       public PhoneNumber() {
           this.phoneNumber = number;
       }

       public void printRussianCountryCode() {

           //ошибка! локальная переменная должна быть объявлена How final!
           System.out.println(russianCountryCode);
       }

   }

   //...code валидации номера
}
Bu ýerde düzüji iki ýalňyşlyk goýberdi. Emma bu ýerde hemme zat tertipli:
public void validatePhoneNumber(final String number) {

   final String russianCountryCode = "+7";

    class PhoneNumber {

       private String phoneNumber;


       public PhoneNumber() {
           this.phoneNumber = number;
       }

       public void printRussianCountryCode() {

           System.out.println(russianCountryCode);
       }

    }

   //...code валидации номера
}
Indi leksiýanyň başyndaky koduň düzülmezliginiň sebäbini bilýärsiňiz: Java 7-de ýerli synpda diňe finalmetod parametrlerine we finalýerli üýtgeýjilere girip bolýar. Java 8-de ýerli synplaryň özüni alyp barşy üýtgedi. Diliň bu wersiýasynda ýerli synpda diňe finalýerli üýtgeýänlere we parametrlere däl, eýsem-de bolsa elýeterlilik bar effective-final. Effective-finalbaşlangyçdan bäri gymmaty üýtgemän üýtgeýän. Mysal üçin, Java 8-de konsola üýtgeýjini aňsatlyk bilen görkezip bileris russianCountryCode, bolmasa-da final. Esasy zat, manysyny üýtgetmeýär. Bu mysalda hemme zat bolmalysy ýaly işleýär:
public void validatePhoneNumber(String number) {

  String russianCountryCode = "+7";

    class PhoneNumber {

       public void printRussianCountryCode() {

           //в Java 7 здесь была бы ошибка
           System.out.println(russianCountryCode);
       }

    }

   //...code валидации номера
}
Emma üýtgeýjiniň bahasyny başlangyçdan derrew üýtgeden bolsak, kod düzülmez.
public void validatePhoneNumber(String number) {

  String russianCountryCode = "+7";
  russianCountryCode = "+8";

    class PhoneNumber {

       public void printRussianCountryCode() {

           //error!
           System.out.println(russianCountryCode);
       }

    }

   //...code валидации номера
}
Aöne ýerli synpyň içerki synpyň bir görnüşi bolmagy hiç zat däl! Olaryň umumy pikirleri hem bar. Classerli synpyň daşarky synpyň ähli (hatda hususy) meýdanlaryna we usullaryna elýeterliligi bar: statiki we statik däl. Mysal üçin, tassyklaýjy synpymyza statiki meýdan goşalyň String phoneNumberRegex:
public class PhoneNumberValidator {

   private static String phoneNumberRegex = "[^0-9]";

   public void validatePhoneNumber(String phoneNumber) {
       class PhoneNumber {

           //......
       }
   }
}
Barlamak bu statiki üýtgeýjiniň kömegi bilen amala aşyrylar. Usul, oňa berlen setirde " [^0-9]" "(ýagny, 0-dan 9-a çenli san däl) adaty aňlatma gabat gelmeýän nyşanlaryň bardygyny ýa-da ýokdugyny barlaýar. Bu üýtgeýjini ýerli synpdan aňsatlyk bilen alyp bileris PhoneNumber. Mysal üçin, alyjy ýazyň:
public String getPhoneNumberRegex() {

   return phoneNumberRegex;
}
Classeserli synplar içerki synplara meňzeýär, sebäbi statiki agzalary kesgitläp ýa-da yglan edip bilmeýär. Statik usullardaky ýerli synplar diňe ýapyk synpyň statiki agzalaryna salgylanyp biler. Mysal üçin, ýapylýan synpyň üýtgeýjisini (meýdany) statik diýip kesgitlemeseňiz, Java düzüjisi ýalňyşlyk döredýär: "Statik däl üýtgeýjini statiki kontekstden görkezip bolmaz." Classeserli synplar statik däl, sebäbi öz içine alýan blok agzalaryna girip bilýär. Şol sebäpli, statiki beýannamalaryň köpüsini öz içine alyp bilmeýär. Blokyň içinde interfeýs yglan edip bilmersiňiz; Interfeýsler tebigatda statikdir. Bu kod düzülmez:
public class PhoneNumberValidator {
   public static void validatePhoneNumber(String number) {
       interface I {}

       class PhoneNumber implements I{
           private String phoneNumber;

           public PhoneNumber() {
               this.phoneNumber = number;
           }
       }

       //...code валидации номера
   }
}
Emma daşarky synpyň içinde interfeýs yglan edilse, synp PhoneNumberony durmuşa geçirip biler:
public class PhoneNumberValidator {
   interface I {}

   public static void validatePhoneNumber(String number) {

       class PhoneNumber implements I{
           private String phoneNumber;

           public PhoneNumber() {
               this.phoneNumber = number;
           }
       }

       //...code валидации номера
   }
}
Classeserli synplar statiki başlangyçlary (başlangyç bloklary) ýa-da interfeýsleri yglan edip bilmeýärler. Localöne ýerli synplarda hemişelik üýtgeýänler ( static final) bolsa statiki agzalar bolup biler. Localerli synplar! Görşüňiz ýaly, içerki synplardan köp tapawudy bar. Olaryň işleýşine düşünmek üçin hatda dil wersiýasynyň aýratynlyklaryna çümmeli bolduk :) Indiki leksiýada, näbelli içki synplar - höwürtgelenen synplaryň soňky topary hakda gürleşeris. Okuwyňyz bilen üstünlik arzuw ediň! :)
Teswirler
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION