فصل 22: پکیج ها در جاوا و تنظیم کنندگان سطح دسترسی (Access Modifiers)

03 شهریور 1397
access-modifiers-java

پکیج در جاوا گروهی از کلاس‌ها، اینترفیس ها و زیر پکیج ها هستند.

پکیج ها به دو گونه هستند، پکیج های داخلی و پکیج های ساخته کاربر. تعداد زیادی پکیج داخلی مانند io ،lang و awt وجود دارد. در ادامه طرز دسترسی و ساخت پکیج ها را بررسی می کنیم.

مزایای پکیج کردن

  1. دسته بندی کلاس ها و اینترفیس ها به گونه ای که به راحتی نگهداری شود.
  2. برای محدود کردن دسترسی مورد استفاده قرار می گیرد.
  3. در صورت یکسانی اسم چندین کلاس، می توان از پکیج برای میسر کردن این اتفاق انجام داد.

پکیج های جاوا

تعریف پکیج

//save as Simple.java  
package mypack;  
public class Simple{  
 public static void main(String args[]){  
    System.out.println("Welcome to package");  
   }  
}

کامپایل پکیج جاوا

در صورتی که از IDE خاصی استفاده نمی کنید، از سینتکس زیر پیروی کنید:

avac -d directory javafilename

به عنوان مثال:

javac -d . Simple.java  

سویچ –d برای مشخص کردن مکانی است که فایل کلاس های ساخته شده در آنجا قرار می گیرند. به جای این سویچ می توانید مکان مورد نظر خود را قرار دهید و در صورتی که می خواهید در همین دایرکتوری پکیج را نگه دارید، آدرس خود را پس از نقطه وارد کنید.

برای اجرای کلاس هم به شکل زیر عمل کنید:

کامپایل : javac -d . Simple.java
اجرا : java mypack.Simple
Output:Welcome to package

-d هم چنان برای مشخص کردن مکان استفاده می شود.

دسترسی به پکیج از پکیج های دیگر

سه راه برای اینکار وجود دارد:

  1. وارد کردن package.*
  2. وارد کردن package.classname
  3. استفاده از اسم کامل

استفاده از package.*

در این صورت تمام کلاس ها و اینترفیس های پکیج مورد نظر غیر از زیر پکیج ها در دسترس شما قرار میگیرن. از واژه import برای در دسترس قرار دادن این موارد استفاده می شود. به مثال زیر نگاه کنید:

ورودی:

//save by A.java  
package pack;  
public class A{  
  public void msg(){System.out.println("Hello");}  
}
//save by B.java  
package mypack;  
import pack.*;  
  
class B{  
  public static void main(String args[]){  
   A obj = new A();  
   obj.msg();  
  }  
}

خروجی:

Output:Hello

استفاده از package.classname

در این صورت تنها کلاس موردنظر وارد می شود.

ورودی:

/save by A.java  
  
package pack;  
public class A{  
  public void msg(){System.out.println("Hello");}  
}
//save by B.java  
package mypack;  
import pack.A;  
  
class B{  
  public static void main(String args[]){  
   A obj = new A();  
   obj.msg();  
  }  
}

خروجی:

Output:Hello

استفاده از نام کامل

در صورتی که از این روش استفاده کنید، تنها کلاسی که مشخص کردید در دسترس خواهد بود و هر موقع که با آن کلاس کار داشته باشید، مجبور به استفاده از نام کامل آن خواهید شد. این روش زمانی به کار گرفته می شود که دو پکیج دارای کلاس های هم نام باشند، برای مثال پکیج java.util و java.sql دارای کلاس Date می باشند.

ورودی:

//save by A.java  
package pack;  
public class A{  
  public void msg(){System.out.println("Hello");}  
}
//save by B.java  
package mypack;  
class B{  
  public static void main(String args[]){  
   pack.A obj = new pack.A();//using fully qualified name  
   obj.msg();  
  }  
}

خروجی:

Hello

باز هم تکرار می کنیم که در صورت import کردن یک پکیج، کلاس و اینترفیس زیرپکیج‌ها در دسترس نیستند و باید جداگانه فراخوانی شوند.

زیرپکیج در جاوا

به پکیجی که خود در داخل پکیجی دیگر باشد، زیرپکیج می گویند.

برای مثال در نظر بگیرید که شرکت سان یک پکیج به نام java ایجاد کرده است، با اینحال مجددا پکیج هایی به نام lang یا io را در پکیج جاوا ایجاد کرده است تا کلاس‌های مختلفی را در آنها بسازد. برای مثال کلاس های Reader و Writer در پکیج io هستند و کلاس Socket در پکیج net. به مثال زیر دقت کنید:

ورودی:

package com.javatpoint.core;  
class Simple{  
  public static void main(String args[]){  
   System.out.println("Hello subpackage");  
  }  
}
کامپایل: javac -d . Simple.java
اجرا: java com.javatpoint.core.Simple

خروجی:

Hello subpackage

چگونه فایل کلاس را به یک دایرکتوری دیگر منتقل کنیم؟

در صورتی که بخواهید به عنوان مثال فایل کلاس، A.java را در فولدر classes در درایو C بریزید آنگاه به این ترتیب عمل می شود:

//save as Simple.java  
package mypack;  
public class Simple{  
 public static void main(String args[]){  
    System.out.println("Welcome to package");  
   }  
}

برای کامپایل:

 e:\sources> javac -d c:\classes Simple.java

برای اجرا:

e:\sources> set classpath=c:\classes;.;
e:\sources> java mypack.Simple

راه دیگر اجرای این برنامه استفاده از سویچ classpath می باشد. از این سویچ برای نشان دادن مسیری که برای پیدا کردن فایل کلاس باید جستجو شود استفاده می شود. دقت کنید:

راه های لود فایل های کلاس یا jar

دو روش برای انجام اینکار به شکل دائمی و موقتی است:

موقتی:

  • با استفاده از سویچ classpath
  • با مشخص کردن classpath از طریق cmd

دائمی

  • با مشخص کردن classpath در System Variables
  • با ساختن فایل jar که شامل تمام فایل های کلاس می باشد و کپی کردن آن در فولدر jre/lib/ext

دقت کنید که تنها یک کلاس عمومی را می توان در فایل منبع جاوا نگه داشت و آنرا با همان نام کلاس باید ذخیره کرد. دقت کنید به مثال زیر:

//save as C.java otherwise Compilte Time Error  
  
class A{}  
class B{}  
public class C{}

چگونه دو کلاس عمومی را در یک پکیج قرار دهیم؟

اگر می خواهید دو کلاس عمومی را داشته باشید آنگاه دو فایل منبع جاوا دارای کلاس عمومی داشته باشید اما نام پکیج را تغییر ندهید. برای مثال:

//save as A.java  
  
package javatpoint;  
public class A{}
//save as B.java  
  
package javatpoint;  
public class B{}

تنظیم کنندگان سطح دسترسی یا Access modifiers در جاوا

به طور کلی دو نوع تنظیم کننده در جاوا وجود دارد، تنظیم کنندگان سطح دسترسی و آن دسته که به سطح دسترسی ارتباطی ندارند. تنظیم کنندگان سطح دسترسی محدوده یک متغیر، کلاس یا متد را مشخص میکند.

4 تنظیم کننده سطح دسترسی وجود دارد که عبارتند از:

  • Public
  • Private
  • Default
  • Protected

از تنظیم کنندگانی که به دسترسی مرتبط نیستند می توان به abstract، transient و static اشاره کرد.

Private

در صورتی که سطح دسترسی private تعریف شود، تنها در همان کلاس در دسترس است. به مثال زیر دقت کنید که با ارور موقع کامپایل مواجه می شویم:

class A{  
private int data=40;  
private void msg(){System.out.println("Hello java");}  
}  
  
public class Simple{  
 public static void main(String args[]){  
   A obj=new A();  
   System.out.println(obj.data);//Compile Time Error  
   obj.msg();//Compile Time Error  
   }  
}

در صورتی که یک کانستراکتور یا سازنده جاوا را خصوصی تعریف کنیم، آنگاه نمی توانیم نمونه ای از آن کلاس ساخت، دقت کنید:

class A{  
private A(){}//private constructor  
void msg(){System.out.println("Hello java");}  
}  
public class Simple{  
 public static void main(String args[]){  
   A obj=new A();//Compile Time Error  
 }  
}

نکته ای که وجود دارد این است که نمی توان کلاس های غیر داخلی را به شکل protected و default تعریف کرد.

Default

در صورتی که  از هیچ تنظیم کننده دسترسی‌ای استفاده نشود، آنگاه default در نظر گرفته می شود.

به مثال زیر دقت کنید که از انجایی که کلاس به شکل عمومی تعریف نشده است، نمی توان از آن در خارج از پکیج استفاده کرد.

//save by A.java  
package pack;  
class A{  
  void msg(){System.out.println("Hello");}  
}
//save by B.java  
package mypack;  
import pack.*;  
class B{  
  public static void main(String args[]){  
   A obj = new A();//Compile Time Error  
   obj.msg();//Compile Time Error  
  }  
}

Protected

از این تنظیم کننده در صورتی استفاده می شود که بخواهیم در داخل یک پکیج و خارج از آن به شرط استفاده از وراثت استفاده کنیم. دقت کنید که از این تنظیم کننده نمی توان بر روی کلاس ها استفاده کرد.

به مثال زیر که مشابه مثال قبل می باشد دقت کنید. از آنجایی که وراثت استفاده شده است، امکان استفاده از متد msg از طریق وراثت وجود دارد.

//save by A.java  
package pack;  
public class A{  
protected void msg(){System.out.println("Hello");}  
}
//save by B.java  
package mypack;  
import pack.*;  
  
class B extends A{  
  public static void main(String args[]){  
   B obj = new B();  
   obj.msg();  
  }  
}

خروجی:

Hello

Public

این تنظیم کننده باعث می شود که دسترسی از همه جا برقرار باشد و بازترین محدوده ممکن را دارد.

مثال:

//save by A.java  
  
package pack;  
public class A{  
public void msg(){System.out.println("Hello");}  
}
//save by B.java  
  
package mypack;  
import pack.*;  
  
class B{  
  public static void main(String args[]){  
   A obj = new A();  
   obj.msg();  
  }  
}

خروجی:

Hello

در جدول زیر مقایسه سریع تمامی این access modifier ها رو می بینیم:

تنظیم کننده در کلاس در پکیج خارج از پکیج توسط کلاس فرزند خارج از پکیج
Private بله خیر خیر خیر
Default بله بله خیر خیر
Protected بله بله بله خیر
Public بله بله بله بله

دقت کنید در صورتی  که یک متد را اورراید (Override) کنید، آنگاه متد اورراید (Override) شده نمیتواند محدود تر باشد. به مثال زیر دقت کنید:

class A{  
protected void msg(){System.out.println("Hello java");}  
}  
  
public class Simple extends A{  
void msg(){System.out.println("Hello java");}//C.T.Error  
 public static void main(String args[]){  
   Simple obj=new Simple();  
   obj.msg();  
   }  
}

در این مثال از آنجایی که default از protected محدودتر است، به ارور کامپایل برخورد می کنیم.

نویسنده شوید

دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.