Hi! Sa aralin ngayon, makikilala natin ang konsepto ng mga modifier ng pag-access at isaalang-alang ang mga halimbawa kung paano magtrabaho sa kanila. Siyempre, hindi tama ang pagsasabi ng 'makilala': pamilyar ka na sa karamihan sa kanila mula sa mga nakaraang aralin. Kung sakali, i-refresh natin ang ating memorya sa pinakamahalagang punto. Ang access ng mga modifier ay kadalasang mga keyword na kumokontrol sa pag-access sa iba't ibang bahagi ng iyong code. Bakit 'pinaka madalas'? Dahil ang isa sa mga ito ay nakatakda bilang default nang hindi gumagamit ng isang keyword :) Ang Java ay may apat na access modifier. Inililista namin ang mga ito sa pagkakasunud-sunod mula sa pinaka-mahigpit hanggang sa pinaka 'maluwag':
  • pribado;
  • default (nakikita ang package);
  • protektado;
  • pampubliko.
Tingnan natin ang bawat isa sa kanila at tukuyin kung kailan sila maaaring maging kapaki-pakinabang. At magbibigay kami ng mga halimbawa :)

Ang pribadong modifier

I-access ang mga modifier.  Pribado, protektado, default, pampubliko - 2pribado ay ang pinaka-mahigpit na access modifier. Nililimitahan nito ang visibility ng data at mga pamamaraan sa loob ng isang klase. Alam mo ang modifier na ito mula sa aralin tungkol sa mga getter at setter. Tandaan ang halimbawang ito?

public class Cat {

   public String name;
   public int age;
   public int weight;

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

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
Isinaalang-alang namin ito sa nakaraang aralin. Nakagawa kami ng malubhang pagkakamali dito: Ginagawa naming pampubliko ang aming data, na nagpapahintulot sa mga kapwa programmer na direktang ma-access ang mga field at baguhin ang kanilang mga halaga. Higit pa... ang mga halagang ito ay itinalaga nang walang anumang mga pagsusuri. Nangangahulugan ito na ang aming programa ay maaaring lumikha ng isang pusa na may pangalang "" na may edad na -1000 taon at timbang na 0. Upang malutas ang problemang ito, gumamit kami ng mga getter at setter, at ginamit din ang pribadong modifier upang limitahan ang pag-access sa data.

public class Cat {

   private String name;
   private int age;
   private int weight;

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

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       // input parameter check
       this.name = name;
   }

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       // input parameter check
       this.age = age;
   }

   public int getWeight() {
       return weight;
   }

   public void setWeight(int weight) {
       // input parameter check
       this.weight = weight;
   }
}
Karaniwan, ang paglilimita sa pag-access sa mga field at pagpapatupad ng mga getter at setter ay ang pinakakaraniwang mga halimbawa kung gaano pribadogagamitin sa totoong trabaho. Sa madaling salita, ang pangunahing layunin ng modifier na ito ay upang makamit ang encapsulation sa isang programa. Hindi lang ito nalalapat sa mga field. Isipin na sa iyong programa ay may isang pamamaraan na nagpapatupad ng ilang NAPAKA-komplikadong pag-andar. Ano ang maaari naming imungkahi bilang isang halimbawa? Sabihin nating ang iyong readDataFromCollider() na paraan ay tumatanggap bilang input ng data address, nagbabasa ng data mula sa Large Hadron Collider sa byte na format, kino-convert ang data na ito sa text, isinusulat ito sa isang file, at ini-print ito. Kahit na ang isang paglalarawan ng pamamaraan ay mukhang nakakatakot, upang walang masabi tungkol sa code :) Upang gawing mas nababasa ang code, pinakamahusay na huwag isulat ang lahat ng kumplikadong lohika ng pamamaraan sa isang lugar. Sa halip, dapat nating hatiin ang functionality sa magkakahiwalay na pamamaraan. Halimbawa, ang readByteData()Ang pamamaraan ay responsable para sa pagbabasa ng data, ang paraan ng convertBytesToSymbols() ay nagko-convert ng data na nabasa mula sa collider sa text, ang saveToFile() na paraan ay nagse-save ng natanggap na text sa isang file, at ang printColliderData() na pamamaraan ay nagpi-print ng aming data file. Sa huli, ang aming readDataFromCollider() na pamamaraan ay magiging mas simple:

public class ColliderUtil {

   public void readDataFromCollider(Path pathToData) {
       byte[] colliderData = readByteData(pathToData);
       String[] textData = convertBytesToSymbols(colliderData);
       File fileWithData = saveToFile(textData);
       printColliderData(fileWithData);
   }

   public byte[] readByteData(Path pathToData) {

       // Reads data in bytes
   }

   public String[] convertBytesToSymbols(byte[] colliderDataInBytes) {

       // Converts bytes to characters
   }

   public File saveToFile(String[] colliderData) {

       // Saves read data to a file
   }

   public void printColliderData(File fileWithColliderData) {

       // Prints data from the file
   }
}
Gayunpaman, tulad ng maaalala mo mula sa aralin tungkol sa mga interface, ang gumagamit ay nakakakuha lamang ng access sa panlabas na interface. At ang aming 4 na pamamaraan ay hindi bahagi nito. Ang mga ito ay mga pamamaraan ng katulong: nilikha namin ang mga ito upang mapabuti ang pagiging madaling mabasa ng code at hindi magsiksik ng apat na magkakaibang gawain sa isang paraan. Hindi mo kailangang bigyan ang user ng access sa mga pamamaraang ito. Kung ang mga user ay may access sa convertBytesToSymbols() na paraan kapag nagtatrabaho sa collider, malamang na malito lang sila sa pamamaraan at magtataka kung para saan ito. Anong mga byte ang na-convert? Saan sila nanggaling? Bakit i-convert ang mga ito sa text? Ang logic na isinagawa sa paraang ito ay hindi bahagi ng interface na nakalantad sa user. Tanging ang readDataFromCollider()Ang pamamaraan ay bahagi ng interface. Kaya ano ang gagawin natin sa apat na 'panloob' na pamamaraang ito? Tama! Gamitin ang pribadong modifier upang limitahan ang pag-access sa kanila. Ang paggawa nito ay nagbibigay-daan sa kanila na mapayapang gawin ang kanilang trabaho sa loob ng klase nang hindi nalilito ang user, na hindi kailangang malaman ang lohika ng bawat indibidwal na pamamaraan.

public class ColliderUtil {

   public void readDataFromCollider(Path pathToData) {
       byte[] colliderData = readByteData(pathToData);
       String[] textData = convertBytesToSymbols(colliderData);
       File fileWithData = saveToFile(textData);
       printColliderData(fileWithData);
   }

   private byte[] readByteData(Path pathToData) {
       // Reads data in bytes
   }

   private String[] convertBytesToSymbols(byte[] colliderDataInBytes) {
       // Converts bytes to characters
   }

   private File saveToFile(String[] colliderData) {
       // Saves read data to a file
   }

   private void printColliderData(File fileWithColliderData) {
       // Prints data from the file
   }
}

Ang protektadong modifier

Ang susunod na pinaka mahigpit na modifier ay protektado . I-access ang mga modifier.  Pribado, protektado, default, pampubliko - 3Ang mga field at pamamaraan na minarkahan ng protektadong access modifier ay makikita:
  • sa loob ng lahat ng klase na kasama sa parehong pakete gaya ng sa amin;
  • sa lahat ng klase na nagmamana ng aming klase.
Sa una, mahirap isipin kung kailan ito maaaring kailanganin. Huwag magtaka: may mas kaunting mga kaso ng paggamit para sa protektado kaysa para sa pribado , at ang mga ito ay napaka-espesipiko. Isipin na mayroon kaming abstract na klase ng AbstractSecretAgent na kumakatawan sa isang lihim na ahente sa ilang serbisyo ng paniktik, pati na rin ang isang top_secret na pakete na naglalaman ng klase na ito at mga inapo nito. Ang mga kongkretong klase tulad ng FBISecretAgent , MI6SecretAgent , MossadSecretAgent , atbp. ay namamana nito. Sa loob ng abstract class, gusto naming magpatupad ng agent counter. Tataas ito kapag may ginawang bagong ahente sa isang lugar sa programa. package top_secret;

public abstract class AbstractSecretAgent {

   public static int agentCount = 0;
}
Ngunit ang aming mga ahente ay sikreto! Nangangahulugan ito na dapat nilang malaman at walang iba kung ilan sa kanila ang umiiral. Madali nating maidaragdag ang protektadong modifier sa field ng agent_counter . Kung gayon ang mga pagkakataon ng iba pang mga klase ng lihim na ahente at iba pang mga klase na matatagpuan sa aming top_secret na pakete ay makakakuha ng halaga nito.

public abstract class AbstractSecretAgent {

   protected static int agent_counter = 0;
}
At iyon ang uri ng espesyal na gawain na nangangailangan ng protektadong modifier :)

Ang package na nakikitang modifier

Ang susunod sa listahan ay ang default na modifier, na kilala rin bilang package visible modifier. Hindi ito ipinahiwatig ng isang keyword, dahil inilalapat ito ng Java bilang default sa lahat ng mga field at pamamaraan. Kung isusulat mo ang sumusunod sa iyong code:

int x = 10
ang x variable ay magkakaroon ng package na ito na nakikitang access. Madaling tandaan kung ano ang ginagawa nito. Karaniwang, default = protected inheritance :) Tulad ng protected modifier, limitado ang application nito. Kadalasan, ginagamit ang default na access sa isang package na may ilang mga utility class na hindi nagpapatupad ng functionality ng lahat ng iba pang klase sa package. Magbigay tayo ng halimbawa. Isipin na mayroon kaming isang 'serbisyo' na pakete. Naglalaman ito ng iba't ibang klase na gumagana sa isang database. Halimbawa, mayroong klase ng UserService na nagbabasa ng data ng user mula sa database, isang CarServiceklase na nagbabasa ng data ng kotse mula sa parehong database, at iba pang mga klase, na ang bawat isa ay gumagana sa mga partikular na uri ng mga bagay at nagbabasa ng kaukulang data mula sa database.

package services;

public class UserService {
}

package services;

public class CarService {
}
Ngunit magiging madali para sa data sa database na nasa isang format at kailangan namin ito sa isa pa. Isipin na ang mga petsa ng kapanganakan ng mga user sa database ay naka-store bilang <TIMESTAMP WITH TIME ZONE>...

2014-04-04 20:32:59.390583+02
...at sa halip ay kailangan namin ang pinakasimpleng bagay — isang java.util.Date . Upang malutas ang problemang ito, sa loob ng package ng mga serbisyo , maaari tayong lumikha ng isang espesyal na klase ng Mapper . Ito ay magiging responsable para sa pag-convert ng data mula sa database sa aming mga pamilyar na Java object. Isang simpleng klase ng katulong. Karaniwan naming idineklara ang lahat ng klase bilang pampublikong klase ClassName , ngunit hindi ito kinakailangan. Maaari naming ideklara ang aming helper class bilang class Mapper . Sa kasong ito, ginagawa pa rin nito ang trabaho nito, ngunit hindi ito nakikita ng sinuman sa labas ng package ng mga serbisyo !

package services;

class Mapper {
}


package services;

public class CarService {

   Mapper mapper;
}
At narito ang pangunahing pangangatwiran: bakit ang sinuman sa labas ng package ay kailangang makakita ng isang helper class na gumagana lamang sa mga klase sa package na iyon?

Ang pampublikong modifier

At ang huling ngunit hindi bababa sa, ang pampublikong modifier! Nakilala mo ang modifier na ito sa iyong unang araw ng pag-aaral sa CodeGym sa unang pagkakataon na nagpatakbo ka ng pampublikong static void main(String[] args) . I-access ang mga modifier.  Pribado, protektado, default, pampubliko - 4Ngayong napag-aralan mo na ang aralin tungkol sa mga interface, malinaw na sa iyo ang layunin nito :) Pagkatapos ng lahat, ang pampublikong modifier ay nilikha upang magbigay ng isang bagay sa mga gumagamit. Halimbawa, ang interface ng iyong programa. Ipagpalagay na nagsulat ka ng isang programa ng tagasalin na maaaring magsalin ng tekstong Ruso sa Ingles. Gumawa ka ng paraan ng pagsasalin (String textInRussian) na nagpapatupad ng lahat ng kinakailangang lohika. Minarkahan mo ang paraang ito ng salitang public , at ngayon ay bahagi na ito ng interface:

public class Translator {

   public String translate(String textInRussian) {

       // Translates text from Russian to English
   }
}
Maaari mong itali ang paraang ito sa pindutang 'Isalin' sa screen at tapos ka na! Kahit sino ay maaaring gumamit nito. Ang mga bahagi ng code na minarkahan ng pampublikong modifier ay inilaan para sa end user. Nagbibigay ng totoong buhay na halimbawa, ang pribado ay para sa lahat ng prosesong nagaganap sa loob ng isang TV, ngunit ang pampubliko ay para sa mga button sa remote control na ginagamit upang pamahalaan ang TV. Higit pa rito, hindi kailangang malaman ng gumagamit kung paano binuo ang telebisyon o kung paano ito gumagana. Ang remote control ay ang hanay ng mga pampublikong -paraan: on() , off() , nextChannel() , previousChannel() , increaseVolume() , lowerVolume() atbp. Upang palakasin ang iyong natutunan, iminumungkahi naming manood ka ng isang video lesson mula sa aming Java Course