محلی برای یادگیری جاوا

۸ مطلب با موضوع «شی گرایی» ثبت شده است

اصل اول Single Responsibility

اولین اصل تک مسیولیتی است:

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

مثالی که برای این موضوع می توان زد چاقوهای سوییسی هستند که یک وسیله چند مسیولیت دارد. و در صورت نیاز به تغییر مثلا تیغه ی قیچی تمام تیغه های دیگر نیز ممکن است تاثیر بپذیرند.

SingleResponsibility

ولی در صورت جدا بودن هر وسیله تعویض یا تغییر آن مستقل از دیگر وسایل است.

SingleResponsibility SOLID

۰۷ خرداد ۹۶ ، ۱۴:۱۱ ۰ نظر موافقین ۱ مخالفین ۰
پریسا

SOLID

SOLID سرنام پنج اصل از طراحی شی گرا (Object-Oriented Design) است.

S - Single-responsiblity principle

O - Open-closed principle

L - Liskov substitution principle

I - Interface segregation principle

D - Dependency Inversion Principle

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

۲۵ ارديبهشت ۹۶ ، ۱۳:۵۷ ۱ نظر موافقین ۰ مخالفین ۰
پریسا

Abstraction یا تجرید

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

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

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

  

abstarction

  

پس برای کد کردن مثال زیر ما یک کلاس Abstract به نام Automobile می سازیم که همانطور که می دانید قابل نمونه سازی نیست و به عنوان پدر کلاس هایی مثل Bus، Car و ... استفاده می شود.

public abstract class Automobile {

protected String type;
protected int numberOfDoor;
.
.
.

protected abstract void Drive();
...
}

حالا برای مثال از این کلاس برای ارث بری استفاده می کنیم:

public class Car extends Automobile {


@Override
protected void Drive() {

}

public Car()
{

}
}

همانطور که دیده می شود متد Drive از کلاس پدر Override شده است و اینکار اجباریست چون Drive در کلاس پدر بدنه ندارد. 

در مرحله آخر شی pride را می سازیم و از آن استفاده می کنیم:

public class Main {
public static void main(String[] args) {
Car pride= new Car();
}
}

۰۷ آذر ۹۴ ، ۲۳:۰۴ ۴ نظر موافقین ۱ مخالفین ۰
پریسا

Polymorphism یا چند ریختی

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

قبل از ذکر مثال به طور ضمنی توضیحی در مورد Overriding داده خواهد شد. البته به طور حتم برنامه نویسان با Overriding  آشنا هستند.

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

public class Parent {
public void printClassName(){
System.out.println("Parent");
}
}
public class Child extends Parent {
public void printClassName(){
System.out.println("Child");
}
}

public class Main {
public static void main(String[] args) {
Parent p= new Parent();
p.printClassName();

Child c= new Child();
c.printClassName();
}
}

خروجی چاپ شده به شکل زیر خواهد بود:

Parent
Child

پس واضح است که وقتی یک متد override می شود زمانی که بر روی نمونه پدر صدا زده می شود متد پدر و زمانی که روی نمونه فرزند می شود صدا زده می شود متد مربوط به فرزند را اجرا می کند.

حال به مفهوم چند ریختی می پردازیم:

چند ریختی در شی گرایی

تصویر بالا را قبلا در پست مربوط به مفاهیم شی گرایی استفاده  کرده بودم. مثال این پست هم در مورد همین تصویر است.

فرض می کنیم یک interface به نام Animal داریم که parent کلاس های مربوط به تمام حیوانات است. در این کلاس یک متد ()Speak داریم که صدای حیوانات را پرینت می کند:

public interface Animal {
void speak();
}

مطابق شکل سه حیوان مختلف داریم که از Animal ارث می برند و متد speak را override می کنند:

public class Dog implements Animal {

public void speak(){
System.out.println("Woof");
}
}
public class Cat implements Animal {
public void speak() {
System.out.println("Meow");
}
}
public class Duck implements Animal {
public void speak(){
System.out.println("Quack");
}
}

حال اگر به شکل زیر از حیوانات نمونه بسازیم شاهد چند ریختی خواهیم بود:

public class Main {
public static void main(String[] args) {

Animal animal1= new Cat();
Animal animal2= new Dog();
Animal animal3=new Duck();

animal1.speak();
animal2.speak();
animal3.speak();
}
}

خروجی :

Meow
Woof
Quack

همانطور که در شکل و در خروجی می بینیم با ساخت سه حیوان و صدا کردن یک متد روی آن شاهد خروجی های مختلف هستیم. این حالت و قابلیت شی گرایی چند ریختی نامیده می شود. در واقع حیوان یا animal در spaek شکل های مختلف به خود گرفته است.

۱۹ آبان ۹۴ ، ۲۱:۴۳ ۰ نظر موافقین ۱ مخالفین ۰
پریسا

Constructor یا سازنده 2

 پست قبل در مورد سازنده کلاس بود. در این پست به سازنده ها در جریان وراثت می پردازم. فرض می کنیم یک کلاس به نام Parent داریم به شکل زیر:

public class Parent {
public Parent()
{
...
}
}

حال فرض می کنیم این کلاس یک subclass به نام Child داشته باشد. همانطور که قبلا اشاره شد در زمان ساخت یک شی یا نمونه (Instance) از کلاس، متد سازنده ی آن فراخوانی می شود. اگر کلاسی فرزند کلاس دیگر باشد در این حالت باید بدانیم که در constructor آن باید constructor کلاس پدر نیز به نوعی فراخوانی شود. این کار از طریق استفاده از متد ()super انجام می شود. به شکل زیر:

public class Child extends Parent {
public Child(){
super();
...
}
}

حال فرض کنیم که constructor کلاس پدر argument هایی به عنوان ورودی دارد. در این حالت باید زمان نوشتن constructor برای فرزند پارامترهای ورودی constructor پدر را درون متد ()super بفرستیم:

public class Parent {
String name;
public Parent(String name)
{
....
}
}
public class Child extends Parent {
public Child(String name){
super(name);
...
}
}

پس طبق آنچه دیده می شود اگر constructor کلاس پدر ورودی داشته باشد constructor کلاس فرزند هم نمی تواند بدون ورودی باشد. اما اینطور نیست. یعنی میتوانیم ورودی های constructor پدر را به روشی ارسال کنیم که constructor کلاس فرزند هیچ ورودی نداشته باشد برای اینکاربه روش زیر می توانیم عمل کنیم:

public class Child extends Parent {
String name="Parisa";
public Child(){
super(name);
...
}
}

قبلا در پست مربوط به static گفت بودم که متغیر های غیر استاتیک متعلق به instance یا نمونه ی کلاس و متغیر های استاتیک متعلق به کلاس هستند. پس برای استفاده از متغییر های غیر استاتیک مانند متغیر name در کلاس Child باید حتما نمونه ای از کلاس Child ساخته شود و کد نوشته شده به شکل بالا دچار خطا می شود. پس با توجه به توضیحات داده شده متغیر name ر اباید بصورت static تعریف کنیم:

public class Child extends Parent {
static String name="Parisa";
public Child(){
super(name);
...
}
}
۱۲ مهر ۹۴ ، ۱۹:۰۲ ۰ نظر موافقین ۱ مخالفین ۰
پریسا

Constructor یا سازنده

همه برنامه نویسان با مفهوم Constructor یا سازنده آشنا هستند. Constructor ها متدهایی بدون خروجی و هم نام با کلاس هستند که زمان ساخت شی ی از کلاس invoke می شوند:

public class Person {
String name;
int age;

public Person() {
...
}
public Person(String name, int age) {
...
}
}

اگر برنامه نویس Constructor ی برای کلاس ننویسد کامپایلر جاوا (javac) یک Constructor پیش فرض برای آن ها تولید می کند. 

برای یک کلاس همانطور که در بالا دیده می شود می توان چندین Constructor نوشت. به این عمل Constructor overloading گفته می شود. که مشابه همان مفهوم Overloading در جاواست.

نکته1: در یک کلاس می توان چندین متد همنام داشت که پارامتر های ورودی آنها متفاوت است به این عمل Overloading گفته می شود.

نکته2: به constructor بدون ورودی اصطلاحا default constructor گفته می شود.

۰۵ مهر ۹۴ ، ۱۶:۳۳ ۰ نظر موافقین ۱ مخالفین ۰
پریسا

Static

در این پست توضیحاتی در مورد Static داده می شود که بیانگر تاثیر این modifier روی متدها و متغییر هاست:

Static method:

فرض می کنیم یک کلاس به نام Person داریم و Person های ما شامل مرد و زن می شوند:

class Person{

String gender;

public Person(String gender){
this.gender=gender;
}
public chooseSet(){
....;
}

public static sleep() {
....;
}
}

 حال فرض کنیم یک متد به نام ()chooseSet در این کلاس داریم. کار این متد انتخاب یک لباس مناسب برای Person است. عمل انتخاب لباس عملی ست که به جنسیت Person ربط دارد پس این متد را روی شی ی که برنامه نویس ساخته (developer object)و جنسیت آن مشخص است صدا میزنیم. به این شکل:

public static void main(){
Person man=new Person("male");
man.chooseSet();
}

حال فرض کنیم یک متد به نام sleep نیز داریم. کار متد sleep دادن اطلاعاتی درمورد خواب انسان است و این موضوع به اشیا ساخته شده توسط برنامه نویس ربطی ندارد. در همین مثال بین خوابیدن زن و مرد تفاوتی وجود ندارد پس بدون ساخت شی توسط برنامه نویس و صرفا با داشتن کلاس Person می توان متد Sleep را صدا زد. در این وضعیت از static استقاده می کنیم. 

public static void main(){
Person.sleep();
}

همانطور که مشاهده می کنید دیگر نیازی به ساخت شی از Person نبود. 

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

Static variable:

مفهوم static برای variable ها هم بسیار مشابه method هاست. فرض کنیم میخوایم تعداد افراد را بشماریم. و در کلاس Person یک متغییر تعریف می کنیم به نام numberOfPerson که بعد از ساخت هر شی از این کلاس یک عدد آن را اضافه می کنیم:

class Person{
int numberOfPerson ;

public Person(String gender){
this.gender=gender;
}
...

}

 در این وضعیت با هر بار ساخت یک شی از Person این متغییر مقدار 0 را به خود می گیرد. و هر مقداری که در آن بریزیم برای instance بعدی هیچ فرقی ندارد، چون همانطور که برای متدها گفته شد در متغیرها هم یک متغیر غیر استاتیک متعلق به نمونه ساخته شده از کلاس است اما یک متغیر استاتیک متعلق یه کلاس است:

    public static void main(){

Person man=new Person("male");
man.numberOfPerson ++; مقدار 1

Person woman=new Person("female");
woman.numberOfPerson ++; مقدار 1

Person boy=new Person("male");
boy.numberOfPerson ++; مقدار 1

Person girl=new Person("female");
girl.numberOfPerson ++; مقدار 1

}

همانطور که در کد بالا دیده می شود هر numberOfPerson مربوط به یک نمونه خاص است در نتیجه با ساخت یک شی جدید نمیتوان انتظار داشت که متغیر numberOfPerson مقدارش در نمونه قبلی را در خود داشته باشد. راه حل این موضوع این است که کاری کنیم که متغیر numberOfPerson به جای اینکه در هر شی مخصوص آن شی باشد بین تمام اشیا بصورت مشترک باشد و در واقع به کلاس متعلق باشد نه به نمونه های کلاس. اینکار با static کردن این متغیر امکان پذیر است. پس تغییرات به شکل زیر خواهد بود:

class Person{
static int numberOfPerson ;

public Person(String gender){
this.gender=gender;
}

...
}
public static void main(){

Person man=new Person("male");
man.numberOfPerson ++; مقدار 1

Person woman=new Person("female");
woman.numberOfPerson ++; مقدار 2

Person boy=new Person("male");
boy.numberOfPerson ++; مقدار 3

Person girl=new Person("female");

girl.numberOfPerson ++; مقدار 4
int i=Person.numberOfPerson; مقدار 4
}

همانطور که مشاهده می کنید چهار شی داریم و مقدار numberOfPerson نیز 4 است. همانطور که در کد بالا دیده می شود زمانی که numberOfPerson استاتیک است با نام کلاس نیز می توانیم به آن دسترسی پیدا کنیم یعنی Person.numberOfPerson. برای فهم بهتر تفاوت به مثال زیر توجه کنید:

با فرض nonstatic بودن numberOfPerson:

public static void main(){
Person man=new Person("male");
man.numberOfPerson =4;

Person woman=new Person("female");
woman.numberOfPerson=40;

Person boy=new Person("male");

boy.numberOfPerson=14;
Print(man.numberOfPerson); نتیجه 4
Print(woman.numberOfPerson); نتیجه 40
Print(boy.numberOfPerson); نتیجه 14
}

با فرض static بودن numberOfPerson:

public static void main(){

Person man=new Person("male");

man.numberOfPerson =4;

Print(man.numberOfPerson); نتیجه 4
Print(Person.numberOfPerson); نتیجه 4


Person woman=new Person("female");
woman.numberOfPerson=40;

Print(man.numberOfPerson); نتیجه 40
Print(woman.numberOfPerson); نتیجه 40
Print(Person.numberOfPerson); نتیجه 40


Person boy=new Person("male");
boy.numberOfPerson=14;

Print(man.numberOfPerson); 1نتیجه 4
Print(woman.numberOfPerson); 1نتیجه 4
Print(boy.numberOfPerson); نتیجه 14
Print(Person.numberOfPerson); نتیجه 14
}

همانطور که دیده می شود زمانی که به هر شکلی مقدار متغیر استاتیک تغییر کند این تغییر در تمام نمونه ها اتفاق می افتد.

۳۰ شهریور ۹۴ ، ۱۲:۰۸ ۲ نظر موافقین ۲ مخالفین ۰
پریسا

شی گرایی

در دنیای برنامه نویسی شیوه های مختلفی برای نوشتن برنامه وجود دارد. یکی از این شیوه های پرکاربرد برنامه نویسی شی گرا (Object Oriented Programming) است. که ساختار و بلوک اصلی در آن شی (Object) است.
در دنیای واقعی مغز اطلاعاتش را به روش شی گرایی از محیط می گیرد و آن ها را پردازش می کند و همین موضوع بن مایه ی بوجود آمدن زبان های شی گرا شد.

برنامه های نوشته شده با این پارادایم، برنامه های ساختار یافته ای هستند که فواید زیر را دارند:
  • خوانایی بالا
  • تست و اصلاح ساده تر
  • سرعت تولید بیشتر
  • پیچیدگی کمتر
  • اعمال ساده تر تغییر
  • دارا بودن قابلیت استفاده مجدد
هر شی، مطابق دنیای واقعی دارای ویژگی (Property یا Attribute) و رفتار (Behavior) است. برای مثال اگر یک اتومبیل را به عنوان شی در نظر بگیریم شامل یکسری ویژگی مانند رنگ، تعداد در، سال ساخت و ... است همچنین یک اتومبیل یکسری رفتارها از خود نشان می دهد مانند: گاز دادن، ترمز کردن و ...
در برنامه نویسی برای داشتن یک شی نیازمند class هستیم و در کلاس مورد نظر معادل ویژگی variable، و معادل رفتار method را داریم.

مفاهیم مهم در شی گرایی:

وراثت(Inheritance):
همانطور که از نام آن مشخص است، به این معناست که یک شی می تواند ویژگی ها و رفتار شی دیگر را به ارث ببرد.

inheritance

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

مخفی سازی (Encapsulation)
به این معناست که یکسری از پیچیدگی ها و جزییات را از دید دیگران پنهان کرد.

مخفی سازی

در شکل یک عروسک دیده می شود که درون آن جزییات و پیچیدگی هایی مشهود است. اما کودک بدون اطلاع از این پیچیدگی ها و احتمالا با زدن یک دکمه به سادگی با آن بازی می کند.
در واقع کپسوله سازی باعث می شود که اشیا بدون اینکه از چگونگی کارکرد یکدیگر با خبر باشند به کار با یکدیگر بپردازند.

چند ریختی (Polymorphism):
به طور ساده می توان چند ریختی را اینگونه تعبیر کرد: یک شی بتواند شکل های مختلفی به خود بگیرد. به طور دقیقتر اینکه یک متد رفتار های مختلفی از خود نشان دهد.

چند ریختی در شی گرایی

همانطور که در شکل پیداست متد speak می تواند به شکل های مختلف اجرا شود.

۲۳ شهریور ۹۴ ، ۱۷:۴۳ ۰ نظر موافقین ۱ مخالفین ۰
پریسا