اپراتور 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 اتفاق افتاده است. انجام اینکار به شکل عادی ممکن نیست و با ارور موقع کامپایل روبه رو می شود. در صورتی که اینکار را به کمک 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 استفاده شود آنگاه یک کلاس انتزاعی داریم که می تواند متد انتزاعی داشته باشد یا نداشته باشد.
بیاید ابتدا مفهوم انتزاع را در جاوا بررسی کنیم:
انتزاع پروسهای است که جزئیات پیاده سازی را پنهان می کنیم و تنها عملکرد را به کاربر نشان می دهیم.
در واقع تنها موارد ضروری به کاربر نشان داده می شود و جزئیات داخلی پنهان می شود. برای مثال هنگام فرستادن پیام کوتاه، تنها متن پیام و شماره گیرنده را کاربر وارد می کند و بقیه موارد از دید کاربر پنهان می ماند. برای رسیدن به انتزاع دو راه وجود دارد:
در صورتی که در تعریف یک کلاس از کلمه کلیدی abstract استفاده شود آنگاه یک کلاس انتزاعی داریم که می تواند متد انتزاعی داشته باشد یا نداشته باشد. نکتهای که وجود دارد این است که از کلاس انتزاعی نمی توان نمونه ساخت، و تنها میتوان از آن ارث بری کرد.
نکاتی که باید در ذهن داشته باشید عبارتند از:
به متدی که 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
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.