CodeGym /Java Blogu /Rastgele /Java'da Erişim Değiştiriciler
John Squirrels
Seviye
San Francisco

Java'da Erişim Değiştiriciler

grupta yayınlandı
MERHABA! Bugünün dersinde, erişim değiştiricileri kavramını tanıyacağız ve bunlarla nasıl çalışılacağına dair örnekleri ele alacağız. Elbette 'tanışalım' demek pek doğru değil: zaten çoğunu önceki derslerden biliyorsunuz. Her ihtimale karşı, en önemli noktayla ilgili hafızamızı tazeleyelim. Değiştirici erişim, genellikle kodunuzun farklı bölümlerine erişimi düzenleyen anahtar kelimelerdir. Neden 'en sık'? Çünkü bunlardan biri, bir anahtar kelime kullanılmadan varsayılan olarak ayarlanmıştır :) Java'nın dört erişim değiştiricisi vardır. Bunları en kısıtlayıcıdan en 'hoşgörülü'ye doğru sıralıyoruz:
  • özel;
  • varsayılan (paket görünür);
  • korumalı;
  • halk.
Her birine bir göz atalım ve ne zaman yararlı olabileceklerini belirleyelim. Ve örnekler vereceğiz :)

özel değiştirici

Erişim değiştiricileri.  Özel, korumalı, varsayılan, genel - 2private, en kısıtlayıcı erişim değiştiricisidir. Verilerin ve yöntemlerin görünürlüğünü tek bir sınıf içinde sınırlar. Bu değiştiriciyi alıcılar ve ayarlayıcılar hakkındaki dersten biliyorsunuz. Bu örneği hatırladınız mı?

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;
   }
}
Bir önceki derste ele almıştık. Burada ciddi bir hata yaptık: Verilerimizi herkese açık hale getirdik, bu da diğer programcıların alanlara doğrudan erişmesine ve değerlerini değiştirmesine olanak sağladı. Üstelik... bu değerler herhangi bir kontrol yapılmadan atanmıştır. Bu, programımızın "" adında -1000 yaşında ve 0 ağırlığında bir kedi yaratabileceği anlamına gelir. Bu sorunu çözmek için alıcılar ve ayarlayıcılar kullandık ve ayrıca verilere erişimi sınırlamak için özel değiştiriciyi kullandık.

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;
   }
}
Temel olarak, alanlara erişimi sınırlandırmak ve alıcıları ve ayarlayıcıları uygulamak, özelin ne kadar özel olduğunun en yaygın örnekleridir.gerçek işlerde kullanılacaktır. Başka bir deyişle, bu değiştiricinin asıl amacı, bir programda kapsülleme sağlamaktır. Bu arada, bu sadece alanlar için geçerli değil. Programınızda bazı ÇOK karmaşık işlevleri uygulayan bir yöntem olduğunu hayal edin. Örnek olarak ne önerebiliriz? ReadDataFromCollider() yönteminizin bir veri adresini girdi olarak kabul ettiğini, Büyük Hadron Çarpıştırıcısından bayt biçimindeki verileri okuduğunu, bu verileri metne dönüştürdüğünü, bir dosyaya yazdığını ve yazdırdığını varsayalım. Yöntemin açıklaması bile korkutucu görünüyor, kod hakkında hiçbir şey söylememek :) Kodu daha okunabilir hale getirmek için, yöntemin tüm karmaşık mantığını tek bir yere yazmamak en iyisi olacaktır. Bunun yerine, işlevselliği ayrı yöntemlere ayırmalıyız. Örneğin, readByteData()method verileri okumaktan sorumludur, convertBytesToSymbols() yöntemi çarpıştırıcıdan okunan verileri metne dönüştürür, saveToFile() yöntemi alınan metni bir dosyaya kaydeder ve printColliderData() yöntemi veri dosyamızı yazdırır. Sonuç olarak, readDataFromCollider() yöntemimiz çok daha basit olacaktır:

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
   }
}
Ancak, arayüzlerle ilgili dersten de hatırlayacağınız gibi, kullanıcı sadece harici arayüze erişebilir. Ve 4 yöntemimiz bunun bir parçası değil. Bunlar yardımcı yöntemlerdir: bunları kodun okunabilirliğini artırmak ve dört farklı görevi tek bir yönteme sıkıştırmamak için oluşturduk. Kullanıcıya bu yöntemlere erişim izni vermeniz gerekmez. Kullanıcıların çarpıştırıcıyla çalışırken convertBytesToSymbols() yöntemine erişimi varsa , büyük olasılıkla yöntem tarafından kafaları karışacak ve bunun ne işe yaradığını merak edeceklerdir. Hangi baytlar dönüştürülür? Nereden geldiler? Neden onları metne dönüştürelim? Bu yöntemde yürütülen mantık, kullanıcıya sunulan arayüzün bir parçası değildir. Yalnızca readDataFromCollider()yöntem arayüzün bir parçasıdır. Peki bu dört 'dahili' yöntemle ne yapıyoruz? Sağ! Bunlara erişimi sınırlamak için özel değiştiriciyi kullanın . Bunu yapmak, her bir yöntemin mantığını bilmesi gerekmeyen kullanıcının kafasını karıştırmadan sınıf içinde barışçıl bir şekilde çalışmalarını gerçekleştirmelerine olanak tanır.

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
   }
}

korumalı değiştirici

Bir sonraki en kısıtlayıcı değiştirici korumalıdır . KorumalıErişim değiştiricileri.  Özel, korumalı, varsayılan, genel - 3 erişim değiştiricisi tarafından işaretlenen alanlar ve yöntemler görünür olacaktır:
  • bizimkiyle aynı pakette yer alan tüm sınıflar içerisinde;
  • sınıfımızı miras alan tüm sınıflarda.
İlk başta, buna ne zaman ihtiyaç duyulabileceğini hayal etmek zor. Şaşırmayın: protected için private'den çok daha az kullanım durumu vardır ve bunlar çok spesifiktir. Bazı istihbarat servislerinde gizli bir ajanı temsil eden bir AbstractSecretAgent soyut sınıfımız ve bu sınıfı ve onun soyundan gelenleri içeren bir top_secret paketimiz olduğunu hayal edin . FBISecretAgent , MI6SecretAgent , MossadSecretAgent vb. gibi somut sınıflar onu miras alır. Soyut sınıfın içinde, bir etmen sayacı uygulamak istiyoruz. Programın herhangi bir yerinde yeni bir ajan oluşturulduğunda artacaktır. top_secret paketi;

public abstract class AbstractSecretAgent {

   public static int agentCount = 0;
}
Ama ajanlarımız gizli! Bu, onların ve başka hiç kimsenin kaç tanesinin var olduğunu bilmemesi gerektiği anlamına gelir. Agent_counter alanına korumalı değiştiriciyi kolayca ekleyebiliriz . Daha sonra top_secret paketimizde bulunan diğer gizli ajan sınıflarının ve diğer sınıfların örnekleri değerini alabilir.

public abstract class AbstractSecretAgent {

   protected static int agent_counter = 0;
}
Ve bu, korumalı değiştiriciyi gerektiren özel bir görevdir :)

paket görünür değiştirici

Listede sonraki sırada , paket görünür değiştiricisi olarak da bilinen varsayılan değiştirici var . Java onu varsayılan olarak tüm alan ve yöntemlere uyguladığından, bir anahtar sözcükle gösterilmez. Aşağıdakileri kodunuza yazarsanız:

int x = 10
x değişkeni bu pakete görünür erişime sahip olacaktır . Ne yaptığını hatırlamak kolaydır. Temel olarak, varsayılan = korumalı kalıtım :) Korumalı değiştirici gibi , uygulaması sınırlıdır. Çoğu zaman varsayılan erişim, paketteki diğer tüm sınıfların işlevlerini uygulamayan bazı yardımcı program sınıflarına sahip bir pakette kullanılır. Bir örnek verelim. Bir 'hizmetler' paketimiz olduğunu hayal edin. Bir veritabanı ile çalışan çeşitli sınıflar içerir. Örneğin, veritabanından kullanıcı verilerini okuyan bir UserService sınıfı, bir CarService sınıfı vardır.aynı veritabanından araba verilerini okuyan sınıf ve her biri belirli nesne türleri ile çalışan ve veritabanından karşılık gelen verileri okuyan diğer sınıflar.

package services;

public class UserService {
}

package services;

public class CarService {
}
Ancak veritabanındaki verilerin bir formatta olması kolay olurdu ve ona başka bir formatta ihtiyacımız var. Veritabanındaki kullanıcıların doğum tarihlerinin <ZAMAN DİLİMİ İLE TIMESTAMP> olarak saklandığını düşünün...

2014-04-04 20:32:59.390583+02
... ve bunun yerine en basit nesneye ihtiyacımız var - bir java.util.Date . Bu sorunu çözmek için services paketi içerisinde özel bir Mapper sınıfı oluşturabiliriz . Veri tabanındaki verileri tanıdık Java nesnelerimize dönüştürmekten sorumlu olacaktır. Basit bir yardımcı sınıf. Genellikle tüm sınıfları ClassName genel sınıfı olarak bildiririz , ancak bu bir gereklilik değildir. Yardımcı sınıfımızı basitçe class Mapper olarak ilan edebiliriz . Bu durumda, yine işini yapar, ancak hizmetler paketinin dışında kimse tarafından görülmez !

package services;

class Mapper {
}


package services;

public class CarService {

   Mapper mapper;
}
Ve işte temel mantık: neden bir paketin dışındaki herhangi birinin yalnızca o paketteki sınıflarla çalışan bir yardımcı sınıf görmesi gerekiyor?

genel değiştirici

Ve son fakat en az değil, genel değiştirici! Bu değiştiriciyle, CodeGym'deki çalışmanızın ilk gününde public static void main(String[] args) işlevini ilk kez çalıştırdığınızda tanıştınız . Erişim değiştiricileri.  Özel, korumalı, varsayılan, genel - 4Artık arayüzlerle ilgili dersi çalıştığınıza göre, amacını anladınız :) Ne de olsa, genel değiştirici kullanıcılara bir şeyler vermek için yaratıldı. Örneğin, programınızın arayüzü. Farz edin ki Rusça metni İngilizceye çevirebilen bir tercüman programı yazdınız. Gerekli tüm mantığı uygulayan bir translate(String textInRusça) yöntemi oluşturdunuz . Bu yöntemi public kelimesiyle işaretlediniz ve artık arayüzün bir parçası:

public class Translator {

   public String translate(String textInRussian) {

       // Translates text from Russian to English
   }
}
Bu yöntemi ekrandaki 'Çevir' düğmesine bağlayabilirsiniz ve bitirdiniz! Herkes kullanabilir. Genel değiştirici ile işaretlenen kod bölümleri son kullanıcıya yöneliktir. Gerçek hayattan bir örnek vermek gerekirse, özel , bir TV içinde gerçekleşen tüm işlemler içindir, ancak genel , TV'yi yönetmek için kullanılan uzaktan kumanda üzerindeki düğmeler içindir. Dahası, kullanıcının televizyonun nasıl yapıldığını veya nasıl çalıştığını bilmesine gerek yoktur. Uzaktan kumanda, genel yöntemler kümesidir : on() , off() , nextChannel() , öncekiChannel() , boostVolume() , reduceVolume() vb. Öğrendiklerinizi pekiştirmek için Java Kursumuzdan bir video dersi izlemenizi öneririz.
Yorumlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION