مفاهیم برنامه نویسی شیئ گرا در جاوا — به زبان ساده

۳۶۶ بازدید
آخرین به‌روزرسانی: ۰۶ شهریور ۱۴۰۲
زمان مطالعه: ۵ دقیقه
مفاهیم برنامه نویسی شیئ گرا در جاوا — به زبان ساده

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

کلاس

در ادامه به بیان تعریف «کلاس» می‌پردازیم.

کلاس نقطه شروع همه اشیا محسوب می‌شود. کلاس را می‌توان به عنوان یک قالب برای ایجاد شیئ تصور کرد. هر کلاس به طور معمول شامل فیلدهای عضو، متدهای عضو، و یک متد خاص به نام «سازنده» (constructor) است. ما از این متد سازنده برای ساخت اشیایی از روی کلاس استفاده می‌کنیم:

1public class Car {
2  
3    // member fields
4    private String type;
5    private String model;
6    private String color;
7    private int speed;
8  
9    // constructor
10    public Car(String type, String model, String color) {
11        this.type = type;
12        this.model = model;
13        this.color = color;
14    }
15      
16    // member methods
17    public int increaseSpeed(int increment) {
18        this.speed = this.speed + increment;
19        return this.speed;
20    }
21      
22    // ...
23}

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

شیئ

شیءها از کلاس‌ها ساخته می‌شوند و به صورت نمونه‌هایی (Instanse) از کلاس نامیده می‌شوند. بدین ترتیب اشیا با استفاده از سازنده‌ها از کلاس‌ها ساخته می‌شوند:

1Car veyron = new Car("Bugatti", "Veyron", "crimson");
2Car corvette = new Car("Chevrolet", "Corvette", "black");

در کد فوق دو وهله از کلاس Car ایجاد کرده‌ایم.

تجرید

وظیفه «تجرید» (Abstraction) پنهان‌سازی پیچیدگی‌های پیاده‌سازی و عرضه اینترفیس‌های ساده‌تر است. برای نمونه اگر یک رایانه را در نظر بگیریم، ما تنها اینترفیس بیرونی آن را می‌بینیم که شامل ضروری‌ترین موارد مورد نیاز برای تعامل با آن است، در حالی که تراشه‌ها و مدارهای داخلی رایانه از دید کاربر پنهان شده است. در برنامه‌نویسی شیئ گرا تجرید به معنی پنهان کردن جزییات پیچیده پیاده‌سازی یک برنامه است. بدین ترتیب صرفاً API مورد نیاز برای استفاده از پیاده‌سازی عرضه می‌شود. در جاوا با استفاده از اینترفیس‌ها و «کلاس‌های مجرد» (Abstract Classes) به تجرید دست پیدا می‌کنیم.

کپسوله‌سازی

وظیفه مفهوم «کپسوله‌سازی» (Encapsulation) پنهان‌سازی حالت بازنمایی داخلی یک شیئ از مصرف‌کننده API است. بدین ترتیب متدهای با دسترسی عمومی متصل به شیئ برای دسترسی‌های خواندن-نوشتن عرضه می‌شوند. این مفهوم امکان پنهان‌سازی اطلاعات خاص و کنترل کردن دسترسی به پیاده‌سازی داخلی را فراهم می‌سازد.

برای نمونه فیلدهای عضو در یک کلاس از دیگر کلاس‌ها پنهان هستند و با استفاده از متدهای عضو می‌توانیم به آن‌ها دسترسی پیدا کنیم. یک روش برای انجام این کار خصوصی ساختن همه فیلدهای داده است که موجب می‌شود تنها از طریق متدهای عضو عمومی قابل دسترسی باشند:

1public class Car {
2 
3    // ...
4    private int speed;
5 
6    public int getSpeed() {
7        return color;
8    }
9 
10    public void setSpeed(int speed) {
11        this.speed = speed;
12    }
13    // ...
14}

در کلاس فوق، speed با استفاده از مادیفایر دسترسی private به صورت خصوصی در آمده است و تنها از طریق متدهای عمومی ()getSpeed و ()setSpeed قابل دسترسی است.

وراثت

مفهوم «وراثت» (Inheritance) مکانیسمی است که امکان دست یافتن به همه مشخصه‌های یک کلاس را در کلاس دیگر فراهم می‌سازد. این کلاس وارث را کلاس فرزند می‌نامیم و کلاس ارث دهنده به صورت کلاس والد یا «سوپرکلاس» (superclass) نامیده می‌شود. در جاوا این کار از طریق بسط دادن کلاس والد انجام می‌یابد. از این رو کلاس فرزند همه مشخصه‌های خود را از والد به ارث می‌برد:

1public class Car extends Vehicle { 
2    //...
3}

هنگامی که یک کلاس بسط می‌یابد، یک رابطه «است» شکل می‌گیرد. بدین ترتیب خودرو (Car) یک وسیله نقلیه (Vihicle) «است» و از این رو همه مشخصات یک وسیله نقلیه را دارد.

ممکن است بپرسید چرا به وراثت نیاز داریم؟ برای پاسخ به این سؤال، سازنده یک وسیله نقلیه را فرض کنید که انواع مختلفی از وسایل نقلیه مانند خودروی سواری، اتوبوس، وانت یا کامیون را می‌سازد. برای ساده‌تر شدن کارها می‌توانیم ویژگی‌ها و مشخصه‌های مشترک را برای همه انواع وسیله نقلیه در یک ماژول (در جاوا کلاس نام دارد) بسازیم. سپس می‌توانیم در مورد انواع منفرد این مشخصه‌ها را از آن ماژول مشترک ارث‌بری کرده و آن مشخصه‌ها را مورد استفاده مجدد قرار دهیم:

1public class Vehicle {
2    private int wheels;
3    private String model;
4    public void start() {
5        // the process of starting the vehicle
6    }
7     
8    public void stop() {
9        // process to stop the vehicle
10    }
11     
12    public void honk() { 
13        // produces a default honk 
14    }
15 
16}

بدین ترتیب یک Car از نوع Vehicle می‌تواند مشخصه‌های خود را از کلاس Vehicle والد به ارث ببرد:

1public class Car extends Vehicle {
2    private int numberOfGears;
3 
4    public void openDoors() {
5        // process to open the doors
6    }
7}

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

1public class ArmoredCar extends Car {
2    private boolean bulletProofWindows;
3     
4    public void remoteStartCar() {
5        // this vehicle can be started by using a remote control
6    }
7}

بدین ترتیب ArmouredCar اقدام به بسط Car می‌کند و Car نیز Vehicle را بسط می‌دهد. از این رو ArmouredCar مشخصه‌های خود را از هر دو کلاس Car و Vehicle ارث‌بری می‌کند. توسعه‌دهندگان در زمان ارث‌بری از کلاس والد می‌توانند برخی پیاده‌سازی‌های متد مربوط به والد را نیز باطل (Override) کنند. این کار به نام «باطل سازی متد» (method overriding) نامیده می‌شود. در مثال مورد بحث ما در مورد کلاس Vehicle یک متد به نام ()honk وجود دارد. کلاس Car اقدام به بسط کلاس Vehicle می‌کند و می‌تواند این متد را باطل کرده و آن را به روشی که می‌خواهد «بوق» (honk) را تولید کند، پیاده‌سازی نماید:

1public class Car extends Vehicle {  
2    //...
3 
4    @Override
5    public void honk() { 
6        // produces car-specific honk 
7    }
8 }

توجه داشته باشید که این وضعیت به نام «چندریختی زمان اجرا» (runtime polymorphism) نیز نامیده می‌شود که در بخش بعدی آن را بیشتر توضیح خواهیم داد.

چندریختی

«چندریختی» (Polymorphism) به امکان زبان‌های برنامه‌نویسی شیئ‌گرا برای تولید پردازش داده‌ها به روش‌های متفاوت بسته به انواع ورودی‌ها گفته می‌شود. این وضعیت در جاوا از طریق ایجاد متدها با نام یکسان و امضای متد متفاوت و اجرای کارکردهای متفاوت انجام می‌یابد:

1public class TextFile extends GenericFile {
2    //...
3  
4    public String read() {
5        return this.getContent()
6          .toString();
7    }
8  
9    public String read(int limit) {
10        return this.getContent()
11          .toString()
12          .substring(0, limit);
13    }
14  
15    public String read(int start, int stop) {
16        return this.getContent()
17          .toString()
18          .substring(start, stop);
19    }
20}

در این مثال، می‌بینیم که متد ()read سه شکل متفاوت با کارکردهای مختلف دارد. این نوع چندریختی استاتیک یا چندریختی زمان کامپایل نام دارد و گاهی اوقات به نام method overloading نیز نامیده می‌شود یک نوع چندریختی زمان اجرا نیز وجود دارد که به نام چندریختی دینامیک نامیده می‌شود و در آن کلاس فرزند، متدهای والد را باطل می‌کند.

1public class GenericFile {
2    private String name;
3  
4    //...
5  
6    public String getFileInfo() {
7        return "Generic File Impl";
8    }
9}

کلاس فرزند می‌تواند کلاس GenericFile را بسط داده و متد ()getFileInfo را باطل سازد:

1public class ImageFile extends GenericFile {
2    private int height;
3    private int width;
4  
5    //... getters and setters
6      
7    public String getFileInfo() {
8        return "Image File Impl";
9    }
10}

سخن پایانی

در این مقاله با مفاهیم اساسی برنامه‌نویسی شیئ‌گرا در جاوا آشنا شدیم. کدهای نمونه معرفی شده در این مقاله را می‌توانید در این ریپوی گیت‌هاب (+) ملاحظه کنید.

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

بر اساس رای ۴ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
baeldung
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *