فصل 20: اپراتور instanceof و کلاس های انتزاعی در جاوا

28 مرداد 1397
abstract-class-java

اپراتور instanceof جاوا برای تست کردن نوع یک شی استفاده می شود.

اپراتور instanceof را به نام اپراتور مقایسه کلاس هم معرفی می کنند، زیرا یک نمونه را با یک کلاس چک میکند. خروجی این اپراتور true یا false است. در صورتی که از این اپراتور با یک متغیر null استفاده کنیم، آنگاه false برمی گرداند.

ابتدا یک مثال از این اپراتور ببینیم:

مثال:

class Simple1{  
 public static void main(String args[]){  
 Simple1 s=new Simple1();  
 System.out.println(s instanceof Simple1);//true  
 }  
}

خروجی:

true

از آنجا که هر شی، نمونه‌ای از کلاس‌های پدر خود نیز می باشد به همین دلیل به عنوان مثال نمونه ساخته شده از کلاس Dog یک نمونه از کلاس Animal نیز به حساب می آید.

یک مثال دیگر:

مثال:

class Animal{}  
class Dog1 extends Animal{//Dog inherits Animal  
  
 public static void main(String args[]){  
 Dog1 d=new Dog1();  
 System.out.println(d instanceof Animal);//true  
 }  
}

خروجی:

true

در مثال پایین، استفاده از instanceof با متغیر null را می بینیم:

مثال:

class Dog2{  
 public static void main(String args[]){  
  Dog2 d=null;  
  System.out.println(d instanceof Dog2);//false  
 }  
}

خروجی:

false

Downcast با استفاده از اپراتور instanceof

در صورتی که نوع کلاس فرزند به شی کلاس پدر اشاره کند، Downcast اتفاق افتاده است. انجام اینکار به شکل عادی ممکن نیست و با ارور موقع کامپایل روبه رو می شود. در صورتی که اینکار را به کمک typecast انجام دهیم، با ارور موقع کامپایل روبه رو نمی شویم اما در نهایت با ClassCastException مواجه خواهید شد:

Dog d=new Animal();//Compilation error
Dog d=(Dog)new Animal();  
//Compiles successfully but ClassCastException is thrown at runtime

حال بیاید اینکار را به کمک اپراتور Instanceof انجام دهیم.

مثال:

class Animal { }  
  
class Dog3 extends Animal {  
  static void method(Animal a) {  
    if(a instanceof Dog3){  
       Dog3 d=(Dog3)a;//downcasting  
       System.out.println("ok downcasting performed");  
    }  
  }  
   
  public static void main (String [] args) {  
    Animal a=new Dog3();  
    Dog3.method(a);  
  }  
    
 }

خروجی:

Output:ok downcasting performed

در مثال زیر downcast را بدون instanceof بررسی می کنیم:

مثال:

class Animal { }  
class Dog4 extends Animal {  
  static void method(Animal a) {  
       Dog4 d=(Dog4)a;//downcasting  
       System.out.println("ok downcasting performed");  
  }  
   public static void main (String [] args) {  
    Animal a=new Dog4();  
    Dog4.method(a);  
  }  
}

خروجی:

Output:ok downcasting performed

در مثال آخر کاربرد instanceof را بهتر بررسی می کنیم:

مثال:

interface Printable{}  
class A implements Printable{  
public void a(){System.out.println("a method");}  
}  
class B implements Printable{  
public void b(){System.out.println("b method");}  
}  
  
class Call{  
void invoke(Printable p){//upcasting  
if(p instanceof A){  
A a=(A)p;//Downcasting   
a.a();  
}  
if(p instanceof B){  
B b=(B)p;//Downcasting   
b.b();  
}  
  
}  
}//end of Call class  
  
class Test4{  
public static void main(String args[]){  
Printable p=new B();  
Call c=new Call();  
c.invoke(p);  
}  
}

خروجی:

b method

کلاس های انتزاعی در جاوا

در صورتی که در تعریف یک کلاس از کلمه کلیدی abstract استفاده شود آنگاه یک کلاس انتزاعی داریم که می تواند متد انتزاعی داشته باشد یا نداشته باشد.

بیاید ابتدا مفهوم انتزاع را در جاوا بررسی کنیم:

انتزاع در جاوا

انتزاع پروسه‌ای است که جزئیات پیاده سازی را پنهان می کنیم و تنها عملکرد را به کاربر نشان می دهیم.

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

  1. کلاس انتزاعی (0 تا 100 درصد)
  2. اینترفیس (100 درصد)

کلاس انتزاعی در جاوا

در صورتی که در تعریف یک کلاس از کلمه کلیدی abstract استفاده شود آنگاه یک کلاس انتزاعی داریم که می تواند متد انتزاعی داشته باشد یا نداشته باشد. نکته‌ای که وجود دارد این است که از کلاس انتزاعی نمی توان نمونه ساخت، و تنها میتوان از آن ارث بری کرد.

نکاتی که باید در ذهن داشته باشید عبارتند از:

  • حتما با کلیدواژه abstract تعریف شود.
  • میتواند متدهای انتزاعی داشته باشد یا نداشته باشد.
  • نمیتوان از آن نمونه ساخت.
  • میتواند کانستراکتور و متدهای استاتیک داشته باشد.
  • میتواند متدهای final داشته باشد تا از تغییر متدها در کلاس های فرزند جلوگیری شود.

متد انتزاعی در جاوا

به متدی که abstract تعریف شود و پیاده‌سازی نشده باشد، متد انتزاعی می گویند.

مثال:

abstract void printStatus();//no method body and abstract

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

مثال:

abstract class Bike{  
  abstract void run();  
}  
class Honda4 extends Bike{  
void run(){System.out.println("running safely");}  
public static void main(String args[]){  
 Bike obj = new Honda4();  
 obj.run();  
}  
}

خروجی:

running safely

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

دقت کنید که بهتر است با استفاده از متدهای کارخانه یا factory method یک شی را پیاده سازی کرد. Factory method متدی است که نمونه کلاس را باز می گرداند. در ادامه درباره متدهای کارخانه بیشتر خواهیم آموخت. به مثال زیر دقت کنید:

مثال:

abstract class Shape{  
abstract void draw();  
}  
//In real scenario, implementation is provided by others i.e. unknown by end user  
class Rectangle extends Shape{  
void draw(){System.out.println("drawing rectangle");}  
}  
class Circle1 extends Shape{  
void draw(){System.out.println("drawing circle");}  
}  
//In real scenario, method is called by programmer or user  
class TestAbstraction1{  
public static void main(String args[]){  
Shape s=new Circle1();//In a real scenario, object is provided through method, e.g., getShape() method  
s.draw();  
}  
}

خروجی:

drawing circle

یک مثال دیگر ببینیم:

مثال:

abstract class Bank{    
abstract int getRateOfInterest();    
}    
class SBI extends Bank{    
int getRateOfInterest(){return 7;}    
}    
class PNB extends Bank{    
int getRateOfInterest(){return 8;}    
}    
    
class TestBank{    
public static void main(String args[]){    
Bank b;  
b=new SBI();  
System.out.println("Rate of Interest is: "+b.getRateOfInterest()+" %");    
b=new PNB();  
System.out.println("Rate of Interest is: "+b.getRateOfInterest()+" %");    
}}

خروجی:

Rate of Interest is: 7 %
Rate of Interest is: 8 %

در مثال زیر یک کلاس انتزاعی داریم که شامل متد، فیلد و کانستراکتور می باشد:

مثال:

//Example of an abstract class that has abstract and non-abstract methods  
 abstract class Bike{  
   Bike(){System.out.println("bike is created");}  
   abstract void run();  
   void changeGear(){System.out.println("gear changed");}  
 }  
//Creating a Child class which inherits Abstract class  
 class Honda extends Bike{  
 void run(){System.out.println("running safely..");}  
 }  
//Creating a Test class which calls abstract and non-abstract methods  
 class TestAbstraction2{  
 public static void main(String args[]){  
  Bike obj = new Honda();  
  obj.run();  
  obj.changeGear();  
 }  
}

خروجی:

       bike is created
       running safely..
       gear changed

نکته بسیار مهم که وجود دارد این است که در صورتی که یک متد را در کلاس انتزاعی تعریف کنید، آنگاه حتما کلاس هم باید انتزاعی باشد در غیر این صورت با ارور زمان کامپایل مواجه می شوید. توجه کنید:

مثال:

class Bike12{  
abstract void run();  
}

خروجی:

compile time error

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

مثال:

interface A{  
void a();  
void b();  
void c();  
void d();  
}  
  
abstract class B implements A{  
public void c(){System.out.println("I am c");}  
}  
  
class M extends B{  
public void a(){System.out.println("I am a");}  
public void b(){System.out.println("I am b");}  
public void d(){System.out.println("I am d");}  
}  
  
class Test5{  
public static void main(String args[]){  
A a=new M();  
a.a();  
a.b();  
a.c();  
a.d();  
}}

خروجی:

Output:I am a
       I am b
       I am c
       I am d
نویسنده شوید
دیدگاه‌های شما

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