"Sasabihin ko sa iyo ang tungkol sa « access modifiers ». Sinabi ko ang tungkol sa kanila minsan, ngunit ang pag-uulit ay isang haligi ng pag-aaral."

Maaari mong kontrolin ang access (visibility) na mayroon ang ibang mga klase sa mga pamamaraan at variable ng iyong klase. Sinasagot ng isang access modifier ang tanong na «Sino ang makaka-access sa pamamaraan/variable na ito?». Maaari kang tumukoy lamang ng isang modifier para sa bawat paraan o variable.

1) " pampubliko " modifier.

Maaaring ma-access ang isang variable, pamamaraan, o klase na may marka ng pampublikong modifier mula saanman sa programa. Ito ang pinakamataas na antas ng pagiging bukas: walang mga paghihigpit.

2) " pribado " modifier.

Ang isang variable, paraan, o klase na minarkahan ng pribadong modifier ay maa-access lang sa klase kung saan ito idineklara. Ang minarkahang paraan o variable ay nakatago mula sa lahat ng iba pang mga klase. Ito ang pinakamataas na antas ng privacy: naa-access lang ng iyong klase. Ang ganitong mga pamamaraan ay hindi minana at hindi maaaring i-override. Bukod pa rito, hindi sila ma-access sa isang descendent na klase.

3)  « Default na modifier».

Kung ang isang variable o pamamaraan ay hindi minarkahan ng anumang modifier, kung gayon ito ay itinuturing na minarkahan ng "default" na modifier. Ang mga variable at pamamaraan na may ganitong modifier ay makikita ng lahat ng klase sa package kung saan idineklara ang mga ito, at sa mga klase lang na iyon. Ang modifier na ito ay tinatawag ding " package " o " package private " na pag-access, na nagpapahiwatig ng katotohanan na ang pag-access sa mga variable at pamamaraan ay bukas sa buong package na naglalaman ng klase.

4) " protektado " modifier.

Ang antas ng access na ito ay bahagyang mas malawak kaysa sa package . Maaaring ma-access ang isang variable, paraan, o klase na may protektadong modifier mula sa package nito (tulad ng "package"), at mula sa lahat ng minanang klase.

Ipinapaliwanag ng talahanayang ito ang lahat:

Uri ng visibility Keyword Access
Iyong klase Ang iyong pakete Pagbaba Lahat ng klase
Pribado pribado Oo Hindi Hindi Hindi
Package (walang modifier) Oo Oo Hindi Hindi
Pinoprotektahan protektado Oo Oo Oo Hindi
Pampubliko pampubliko Oo Oo Oo Oo

Mayroong paraan para madaling matandaan ang talahanayang ito. Isipin na nagsusulat ka ng isang testamento. Hinahati mo ang lahat ng iyong mga bagay sa apat na kategorya. Sino ang maaaring gumamit ng iyong mga bagay?

Sino ang may access Modifier Halimbawa
Ako lang  pribado Personal na journal
Pamilya (walang modifier) Mga larawan ng pamilya
Pamilya at mga tagapagmana protektado ari-arian ng pamilya
lahat pampubliko Mga alaala

"Ito ay tulad ng pag-iisip na ang mga klase sa parehong pakete ay bahagi ng isang pamilya."

"Gusto ko ring sabihin sa iyo ang ilang mga kagiliw-giliw na nuances tungkol sa mga overriding na pamamaraan."

1) Implicit na pagpapatupad ng abstract method.

Sabihin nating mayroon kang sumusunod na code:

Code
class Cat
{
 public String getName()
 {
  return "Oscar";
 }
}

At nagpasya kang lumikha ng klase ng Tiger na nagmamana ng klase na ito, at magdagdag ng interface sa bagong klase

Code
class Cat
{
 public String getName()
 {
   return "Oscar";
 }
}
interface HasName
{
 String getName();
 int getWeight();
}
class Tiger extends Cat implements HasName
{
 public int getWeight()
 {
  return 115;
 }

}

Kung ipapatupad mo lang ang lahat ng nawawalang pamamaraan na sinasabi sa iyo ng IntelliJ IDEA na ipatupad, sa paglaon ay maaari kang gumugol ng mahabang oras sa paghahanap ng bug.

Lumalabas na ang klase ng Tiger ay may getName method na minana mula sa Cat, na kukunin bilang pagpapatupad ng getName method para sa HasName interface.

"Wala akong nakikitang kakila-kilabot tungkol doon."

"Ito ay hindi masyadong masama, ito ay isang malamang na lugar para sa mga pagkakamali na gumapang."

Ngunit maaari itong maging mas masahol pa:

Code
interface HasWeight
{
 int getValue();
}
interface HasSize
{
 int getValue();
}
class Tiger extends Cat implements HasWeight, HasSize
{
 public int getValue()
 {
  return 115;
 }
}

Lumalabas na hindi ka palaging maaaring magmana mula sa maraming mga interface. Mas tiyak, maaari mong mamanahin ang mga ito, ngunit hindi mo maipapatupad ang mga ito nang tama. Tingnan ang halimbawa. Ang parehong mga interface ay nangangailangan na ipatupad mo ang getValue() na paraan, ngunit hindi malinaw kung ano ang dapat nitong ibalik: ang timbang o ang laki? Ito ay medyo hindi kasiya-siya na kailangang harapin.

"Sumasang-ayon ako. Gusto mong magpatupad ng isang pamamaraan, ngunit hindi mo magagawa. Nagmana ka na ng isang pamamaraan na may parehong pangalan mula sa base class. Ito ay nasira."

"Pero may magandang balita."

2) Pagpapalawak ng visibility. Kapag nagmana ka ng isang uri, maaari mong palawakin ang visibility ng isang paraan. Ganito ang hitsura nito:

Java code Paglalarawan
class Cat
{
 protected String getName()
 {
  return "Oscar";
 }
}
class Tiger extends Cat
{
 public String getName()
 {
  return "Oscar Tiggerman";
 }
}
Pinalawak namin ang visibility ng pamamaraan mula protectedsa public.
Code Bakit ito "legal"
public static void main(String[] args)
{
 Cat cat = new Cat();
 cat.getName();
}
Lahat ay mahusay. Dito hindi namin alam na ang visibility ay pinalawig sa isang descendant class.
public static void main(String[] args)
{
 Tiger tiger = new Tiger();
 tiger.getName();
}
Dito namin tinatawag ang pamamaraan na ang visibility ay pinalawak.

Kung hindi ito posible, maaari kaming palaging magdeklara ng paraan sa Tiger:
public String getPublicName()
{
super.getName(); //tawagan ang protektadong paraan
}

Sa madaling salita, hindi namin pinag-uusapan ang anumang paglabag sa seguridad.

public static void main(String[] args)
{
 Cat catTiger = new Tiger();
 catTiger.getName();
}
Kung ang lahat ng mga kundisyon na kinakailangan upang tumawag sa isang pamamaraan sa isang base class ( Cat ) ay nasiyahan, kung gayon sila ay tiyak na nasisiyahan para sa pagtawag sa pamamaraan sa uri ng descendent ( Tiger ). Dahil ang mga paghihigpit sa tawag sa pamamaraan ay mahina, hindi malakas.

"Hindi ako sigurado na lubos kong naiintindihan, ngunit tatandaan ko na posible ito."

3) Pagpapaliit sa uri ng pagbabalik.

Sa isang na-override na paraan, maaari naming baguhin ang uri ng pagbabalik sa isang makitid na uri ng sanggunian.

Java code Paglalarawan
class Cat
{
 public Cat parent;
 public Cat getMyParent()
 {
  return this.parent;
 }
 public void setMyParent(Cat cat)
 {
  this.parent = cat;
 }
}
class Tiger extends Cat
{
 public Tiger getMyParent()
 {
  return (Tiger) this.parent;
 }
}
Na-overrode namin ang method getMyParent, at ngayon ay nagbabalik ito ng Tigerobject.
Code Bakit ito "legal"
public static void main(String[] args)
{
 Cat parent = new Cat();

 Cat me = new Cat();
 me.setMyParent(parent);
 Cat myParent = me.getMyParent();
}
Lahat ay mahusay. Dito hindi namin alam na ang uri ng pagbabalik ng getMyParent method ay pinalawak sa descendant class.

Paano gumagana at gumagana ang «lumang code».

public static void main(String[] args)
{
 Tiger parent = new Tiger();

 Tiger me = new Tiger();
 me.setMyParent(parent);
 Tiger myParent = me.getMyParent();
}
Dito tinatawag namin ang pamamaraan na ang uri ng pagbabalik ay pinaliit.

Kung hindi ito posible, maaari kaming palaging magdeklara ng paraan sa Tiger:
public Tiger getMyTigerParent()
{
return (Tiger) this.parent;
}

Sa madaling salita, walang mga paglabag sa seguridad at/o uri ng mga paglabag sa pag-cast.

public static void main(String[] args)
{
 Tiger parent = new Tiger();

 Cat me = new Tiger();
 me.setMyParent(parent);
 Cat myParent = me.getMyParent();
}
At lahat ay gumagana nang maayos dito, kahit na pinalawak namin ang uri ng mga variable sa base class (Cat).

Dahil sa overriding, ang tamang setMyParent method ay tinatawag.

At walang dapat ipag-alala kapag tumatawag sa getMyParent method , dahil ang return value, bagaman sa Tiger class, ay maaari pa ring italaga sa myParent variable ng base class (Cat) nang walang anumang problema.

Ang mga bagay na tigre ay maaaring ligtas na maiimbak pareho sa mga variable ng Tiger at mga variable ng Cat.

"Oo. Nakuha ko. Kapag nag-o-override ng mga pamamaraan, kailangan mong malaman kung paano gumagana ang lahat ng ito kung ipapasa natin ang ating mga bagay sa code na maaari lamang humawak sa base class at walang alam tungkol sa ating klase. "

"Eksakto! Kung gayon ang malaking tanong ay bakit hindi natin mapaliit ang uri ng return value kapag nag-o-override ng isang pamamaraan?"

"Malinaw na sa kasong ito ang code sa base class ay hihinto sa paggana:"

Java code Pagpapaliwanag ng problema
class Cat
{
 public Cat parent;
 public Cat getMyParent()
 {
  return this.parent;
 }
 public void setMyParent(Cat cat)
 {
  this.parent = cat;
 }
}
class Tiger extends Cat
{
 public Object getMyParent()
 {
  if (this.parent != null)
   return this.parent;
  else
   return "I'm an orphan";
 }
}
Na-overload namin ang getMyParent method at pinaliit ang uri ng return value nito.

Maayos ang lahat dito.

public static void main(String[] args)
{
 Tiger parent = new Tiger();

 Cat me = new Tiger();
 Cat myParent = me.getMyParent();
}
Pagkatapos ang code na ito ay hihinto sa paggana.

Ang getMyParent method ay maaaring magbalik ng anumang instance ng isang Object, dahil ito ay aktwal na tinatawag sa isang Tiger object.

At wala kaming tseke bago ang assignment. Kaya, ganap na posible na ang variable ng Cat-type myParent ay mag-imbak ng isang sanggunian ng String.

"Napakagandang halimbawa, Amigo!"

Sa Java, bago tawagin ang isang pamamaraan, walang suriin kung ang bagay ay may ganoong pamamaraan. Ang lahat ng mga pagsusuri ay nangyayari sa runtime. At ang isang [hypothetical] na tawag sa isang nawawalang paraan ay malamang na magiging sanhi ng pagtatangka ng program na magsagawa ng hindi umiiral na bytecode. Sa huli ay hahantong ito sa isang nakamamatay na error, at sapilitang isasara ng operating system ang programa.

"Whoa. Ngayon alam ko na."