شروع شی گرایی (OOP) در جاوا
حتما واژه Object Oriented Programming و یا به اختصار OOP را شنیده و یا در مقالات بسیاری دیده اید. در این مقاله قصد داریم تا مفهوم و مبانی شی گرایی را با استفاده از زبان جاوا بررسی کنیم تا درک درستی از این مفهوم بسیار کاربردی بدست آید.
در ابتدا باید به یک نکته اشاره کنیم. سری مقالات آموزش Java enterprise همچنان ادامه دارد و در کنار آن به مقالات دیگر جاوا نیز میپردازیم. مقالات Java Enterprise هر هفته منتشر خواهد شد.
شی گرایی میتواند به شما کمک کند تا زمانی که برای برنامه نویسی یک برنامه صرف میکنید, کاهش یابد و همچنین خطا های برنامه راحت تر شناسایی شوند. عملا تکرار یکسری از کد ها در پروژه شما کمتر میشوند و خوانایی برنامه افزایش مییابد.
در مفهوم شی گرایی ابتدا باید کلاس ها را بشناسید. کلاس یک فایل میباشد که در آن یکسری متغیر ها و یکسری توابع وجود دارند. برای آشنایی با مفهوم متغیر ها به اینجا مراجعه کنید. توابع مجموعه از کد ها میباشند که یک نام مختص به آنها وجود دارد و قابل فراخوانی میباشد. در جاوا به توابع method گویند. خود کلاس ها نیز با کلمه کلیدی class شروع میشوند.
class SimpleClass { // this is a class int varibale; // this is a variable void method() { // this is method } }
در کد بالا در خط اول ابتدا یک کلاس را تعریف کرده ایم. سپس در خط بعد یک متغیر را تعریف کرده ایم و در حط بعد یک متد را ایجاد کرده ایم. همانطور که میبینید اجزا کلاس و متد ها درون بلوک هایی قرار میگیرند. قبل از متغیر ها نوع آنها مشخص میشود و برای آشنایی با نوع داده میتوانید به اینجا مراجعه کنید. همانطور که متغیر ها دارای نوع میباشند, متد ها نیز دارای نوع میباشند. نوع داده یک متد مشخص میکند که ما از این متد انتظار داریم تا در ازای پردازشی که درون آن مشخص شده است چنین نوع داده ای را برای ما برگرداند. برای مثال در کد بالا ما از نوع داده ای void استفاده کرده ایم. به این معنی که این متد چیزی برای ما برنمیگرداند و فقط پردازشی را در خود انجام میدهد. در صورتی که بخواهیم یک متد مقداری را برگرداند از کلمه کلیدی return استفاده میکنیم :
int varibale; int getVaribale() { return varibale; }
حال ک با ساختار یک کلاس ساده آشنا شده ایم باید به این موضوع اشاره شود که شی گرایی بر پایه همین کلاس ها و نحوه استفاده آنها میباشد. اگر بخواهیم یک مثال عینی بزنیم, فرض کنید که یک دستور آشپزی دارید و در آن مواد لازم و شیوه پخت غذا مشخص شده است. اگر این مثال را با ساختار کلاس ها انطباق دهید میبینید که مواد لازم همان متغیر ها و شیوه پخت همان متد ها میباشند و دستور پخت نیز کلاس ما میباشد که دربردارنده تمام این موارد میباشد.
حالا اگر شما بهترین و دقیق ترین دستور آشپزی را دراختیار داشته باشید, تا وقتی که آنرا ایجاد نکنید نمیتوانید مزه آن غذا را بچشید. استفاده از کلاس ها نیز با ایجاد یک شی از روی آن امکان پذیر میباشد که به آن object ساختن از روی کلاس گویند. شیوه ساختن یک object نیز به این صورت میباشد :
SimpleClass simpleClassObject=new SimpleClass();
همانطور که در تعریف متغیر ها ابتدا نوع آنها را مشخص میکنیم, به هنگام object سازی نیز باید ابتدا نوع آنرا مشخص کنیم. در حقیقت ما یک متغیر تعریف میکنیم. نوع متغیر ها علاوه بر اینکه میتواند شامل موارد تعریف شده خود زبان مانند string, int, boolean و … باشد, میتواند کلاس ها را نیز شامل شود. برای مثال :
SecurityManager security;
چنین کدی میتواند تعریف یک متغیر از نوع کلاس باشد. حال آنکه نوع آن از نوع کلاس SecurityManager است. درایجاد object نیز ابتدا یک متغیر از نوع کلاس مورد نظر ایجاد میکنیم. مقداری که این متغیر میتواند نگهداری کند نیز باید از نوع کلاس باشد. برای این منظور باید از کلمه کلیدی new استفاده شود. با استفاده از این دستور ما یک شی از روی کلاس ایجاد میکنیم و اجزا درون کلاس قابل استفاده میشوند.
برای استفاده از اجزا درون کلاس باید از “.” استفاده کرد. برای مثال اگر بخواهیم از متد تعریف شده استفاده کنیم به این صورت عمل میکنیم :
SimpleClass simpleClassObject=new SimpleClass(); simpleClassObject.method();
به همین صورت نیز میتوان به متغیر ها نیز دسترسی پیدا کرد.
اکنون که با شیوه دسترسی آشنا شده ایم باید به سطوح دسترسی اشاره کنیم. سه سطح دسترسی در جاوا وجود دارد :
- private : فقط از درون کلاسی که در آن تعریف شده است قابل دسترسی میباشد
- protected : از طریق کلاسی که در آن تعریف شده است و همچنین کلاس هایی که در یک package قرار دارند قابل دسترسی است
- public : از طریق تمام کلاس ها قابل دسترسی میباشد
اگر با کلمه package ها اشنا نیستید, پوشه ها که برای دسته بندی کلاس ها استفاده میشود را package گویند. این سطوح دسترسی برای متغیر ها و متد ها قابل استفاده میباشند. در صورتی که یک متغیر از نوع کلاس تعریف کنید و object متناظر با آن را به آن ارجاع ندهید, در هنگام استفاده از آن متغیر خطا
java.lang.NullPointerException
را دریافت خواهید کرد. JVM برای استفاده از متد ها و متغیر ها نیاز دارد تا آنها را درخانه های حافظه قرار دهد تا قابلیت دسترسی به آنها را داشته باشد. عملا وقتی از روی یک کلاس object ایجاد میشود فضایی از حافظه به متد ها و متغیر های آن اختصاص مییابد. به این ترتیب اگر از روی کلاسی object ایجاد نشود و از متد آن کلاس بخواهیم استفاده کنیم با خطا مواجه میشویم. اما میتوان برای متغیر ها و متد ها فضایی جداگانه در نظر گرفت تا حتی اگر object ایجاد نشد, باز هم بتوان از آن استفاده کرد. به چنین متد ها و یا متغیر هایی static گویند.
همانطور که از کلمه static مشخص است یک فضای حافظه مشخص را به آن متغیر و یا متد اختصاص میدهد. برای تعریف متد و یا متغیر static به این صورت عمل میکنیم :
public static int varibale; // this is a static variable public static void method() { // this is a static method }
برای استفاده از متد static نیز بعد از نام کلاس آن “.” قرار میدهیم و امکان دسترسی به آن فراهم میگردد :
SimpleClass.method();
قوانینی برای نام گذاری در شی گرایی وجود دارد :
- نام کلاس ها با حروف بزگ شروع میشوند و در صورتی که شامل چند کلمه باشد حرف اول هر کلمه را با حروف بزرگ مینویسیم : SimpleClass
- نام متد ها با حروف کوچک شروع میشوند و مانند کلاس ها در صورتی که شامل چند کلمه باشد حرف اول را متغیر را کوچک و حروف اول کلمات بعدی را بزرگ مینویسیم : getStatus()
- متغیر هایی که به صورت static تعریف میشوند را تماما با حروف بزرگ مینویسیم : static int COUNTER
بهتر است سعی کنید برای استفاده و یا اعمال تغییر بر روی متغیر های خود از متد های getter و setter استفاده کنید :
public int getVaribale() { return varibale; } public void setVaribale(int varibale) { this.varibale = varibale; } private int varibale; // this is a variable
به این ترتیب میتوانید متغیر های خود را با انتحاب درست سطوح دسترسی, مدیریت کنید. در اینجا دسترسی به متغیر variable فقط از طریق خود کلاس امکان پذیر میباشد و برای استفاده از مقدار variable باید متد getVariable فراخوانی شود.
نکته مهمی که در شی گرایی باید به آن اشاره کنیم constructor ها هستند. constructor ها اولین متدی است که وقتی از روی یک کلاس object ایجاد میشود فراخوانی میشود. ساختار آن به این صورت است که هم نام با کلاس می باشد و مقداری را برنمیگرداند :
public class SimpleClass { public SimpleClass() { /// this is constructor } }
وقتی بخواهیم متغییر را در هنگام ایجاد object از روی کلاس مقدار دهی کنیم باید آن متغیر را به عنوان ورودی متد در نظر بگیریم :
public SimpleClass(int varibale) { this.varibale=varibale; /// this is constructor }
در اینجا ما یک متغیر از نوع int را به عنوان ورودی constructor قرار داده ایم. در کد بالا کلمه کلیدی this را مشاهده میکنید. این کلمه برای دستری به متغیر ها و متد های درون کلاس میباشد. اگر در کد بالا مقدار this را قرار ندهیم متغیر variable را برابر با خودش قرار میدهد که بی معنی است. با استفاده از کلمه this مقدار یک متغیر با نام variable را که در کلاس وجود دارد, با مقدار variable که به عنوان پارامتر ورودی میباشد, برابر میشود. به هنگام object ساختن نیز باید همانطور که constructor را ایجاد کرده اید, به همان صورت هم object ایجاد کنید. برای مثال از کد بالا در صورتی که بخواهیم object بسازیم باید به این صورت عمل کنیم :
int param = 2; SimpleClass simpleClass=new SimpleClass(param);
در صورتی که ورودی به کلاس ندهیم با خطا مواجه میشویم. اگر constructor تعریف نشود و یا ورودی نداشته باشد به این صورت object میسازیم :
SimpleClass simpleClassObject=new SimpleClass();
تا به اینجا با مقدمات شی گرایی (OOP) آشنا شدیم. اکنون فرض کنید میخواهیم یک برنامه ای ایجاد کنیم که اطلاعات چندین نفر را چاپ کند. اگر از شی گرایی استفاده نکنیم باید به این صورت بنویسیم :
public void greeting() { String user1Name = "vahid"; String user1LastName = "Rajabi"; String user1Code = "205"; String ser1Username = "vhdrjb"; String user2Name = "Zero"; String user2LastName = "Hero"; String user2Code = "102"; String user2Username = "ZeroToHero"; System.out.println("user 1 : "); System.out.println("name : " + user1Name); System.out.println("last name : " + user1LastName); System.out.println("code : " + user1Code); System.out.println("username : " + ser1Username); System.out.println(" ----- "); System.out.println("user 2 :"); System.out.println("name : " + user2Name); System.out.println("last name : " + user2LastName); System.out.println("code : " + user2Code); System.out.println("username : " + user2Username); }
همانطور که میبینید خوانایی کد بسیار بسیار کم میشود. برای رفع این مشکل یک کلاس با نام User ایجاد میکنیم و متغیر های لازم را در آن تعریف میکنیم :
public class User { private String name; private String lastname; private String code; private String username; public String getName() { return name; } public String getLastname() { return lastname; } public String getCode() { return code; } public String getUsername() { return username; } public User(String name, String lastname, String code, String username) { this.name = name; this.lastname = lastname; this.code = code; this.username = username; } public void print() { System.out.println("name : " + getName()); System.out.println("last name : " + getLastname()); System.out.println("code : " + getCode()); System.out.println("username : " + getUsername()); } }
همانطور که در مفهوم constructor گفته شد متغیر هایی که از ابتدای تعریف object نیاز است تا مقدار دهی شوند را مشخص میکنیم و در اینجا مشخصات کاربر است و برای استفاده به این صورت عمل میکنیم :
public void greeting() { User user1 = new User("vahid", "Rajabi", "205", "vhdrjb"); User user2=new User("Zero", "Hero", "102", "ZeroToHero"); System.out.println("User 1"); user1.print(); System.out.println("User 2"); user2.print(); }
همانطور که میبینید کد ساختار بهتری گرفته است و خوانایی آن افزایش یافته است. در این مقاله مقدماتی ازOOP را برای شما توضیح دادیم. در مقاله بعد به مبحث ارث بری میپردازیم.
سری مقالات آموزش شی گرایی (OOP) در جاوا همچنان ادامه دارد.
با ما همراه باشید.
مطالب زیر را حتما مطالعه کنید
از Java به Dart – کلاس و Constructor
آموزش Gradle – اهمیت Project Automation
تفاوت Sequence و List در کاتلین
بهترین محیط های توسعه(IDE) برای جاوا
Open/Closed Principle در قوانین Solid
توابع در زبان برنامه نویسی Kotlin
3 Comments
Join the discussion and tell us your opinion.
دیدگاهتان را بنویسید لغو پاسخ
برای نوشتن دیدگاه باید وارد بشوید.
خیلی عالی ، دقیق و ساده توضیح دادید .
واقعا ممنونم .
سلام !
یه سوال داشتم .. توی کد نویسی اعداد مختلط که داشتم نگاه میکردم ، یه قسمت رو متوجه نشدم .. یه کلاس تعریف شده بود به اسم complex
توی این کلاس متد هایی برای وارد کردن اعداد موهومی و حقیقی تعریف شده
یه متد هایی هم برای خروجی اعداد
قسمتی هم برای چاپ
برای اضافه کردن دو عبارت مختلط ، یه متد به این شکل تعریف شد
Public Complex add (Complex z) {
}
سوال من اینجاست که این complex چیه ؟
اخه مثلا public double یعنی نوع متد ما double هست و double توی جاوا تعریف شده ست … اما complex چیه؟
سلام دوست عزیز. ممنون از همراهیتوت. بعد از کلمه کلیدی public نوع متغیری که توسط این متد برگردونده شده مشخص میشه. مثل مثال خودتون ک double برمیگردونه. حالا یکسری از کلاس ها توی جاوا براشون کلمات کلیدی تعریف شده. مثل کلاس Double که کلمه کلیدی double براش تعریف شده تا دسترسی برای تعریف متغیر ها کمی ساده تر بشه. عملا هیچ فرقی بین این دوتا نیست. پس میشه گفت اون متد شما که public double method هست میتونه به این صورت هم باشه : public Double method. حالا همین حالت برای کلاس های دیگه در نظر بگیرین. مثلا شما از کلاس Complex یه یه طریق خاصی استفاده میکنین. حالا یکسری پردازش توسط یکسری کلاس ها انجام شدند که خروجی اونها از نوع Comple هست. متدی که این پردازش ها توش انجام شدن میتونن نوع Complex رو برگردونن. به بیان ساده تر کلمه بعد Public مشخص کننده کلاس متغیری هست که متد برمیگردونه. در واقع این متد شما مثل همون متد double عمل میکنه ولی نوع متغیری که برمیگردونه از نوع Complex هست. مثلا وقتی یک String تعریف میکنیم, عملا برای کلاس یه مقدار مشخص میکنیم و مقداری که باید نگه داشته باشه از طریق “=” مشخص میکنیم براش. حالا همین متد اگه قراره یک متغیر از نوع String برگردونه میشه : public String method. برای همین این حالت برای همه کلاس ها میتونه استفاده بشه و کلاس متغیری که قراره برگردونده بشه توی همین قسمت مشخص میشه. اون double و این جور کلمه های کلیدی هم فقط برای دسترسی سریع تر به کلاس های مختص به خودشونه. و در واقع متد از همون کلاسشون اسفتاده میکنه.
اگر بازم جایی ابهام داشت میتونین در انجمن مطرح کنین.