ورود

View Full Version : سوال: تفاوت کپسوله سازی و انتزاع ( Encapsulation و Abstraction)



f.beigirad
پنج شنبه 31 اردیبهشت 1394, 23:06 عصر
با سلام و درود

تو تعاریف کپسوله سازی اومده که قرار دادن داده ها و توابعی که روی این داده ها کار میکنند در یک بسته رو کپسوله سازی میگن.
تو تعریف انتزاع هم اومده که به جداسازی و پنهان کردن جزئیات از دید کاربر انتزاع میگن.

خب جفت این دوتا که شد مخفی کردن از دید کاربر.
پس فرقشون چیه؟

من خیلی تو مطالب فارسی گشتم ولی به جواب سوالم نرسیدم.مطالب انگلیسیم که چون یکم بحثش پیچیدس متوجه منظورشون نمیشم.

ممنون میشم با مثال برام توضیح بدین.

ravaei
جمعه 01 خرداد 1394, 22:36 عصر
درود...

کپسوله سازی و انتزاع دو تا مبحث کاملا جدایه :

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


class Adder{
public:
// constructor
Adder(int i = 0)
{
total = i;
}
// interface to outside world
void addNum(int number)
{
total += number;
}
// interface to outside world
int getTotal()
{
return total;
};
private:
// hidden data from outside world
int total;
};
int main( )
{
Adder a;

a.addNum(10);
a.addNum(20);
a.addNum(30);


cout << "Total " << a.getTotal() <<endl;
return 0;
}


تو کد بالا total یک متغیر private هستش و gettotal و addnumber دو تا متد public هستن ... که تو main کلاس رو تعریف کرده چون تو سازنده مقدار اولیه i رو صفر قرار داده پس وقتی در حین ساخت نمونه مقداری به i نده 0 در نظر میگیره ، با استفاده از addnumber مقدار اولیه number رو گرفته و به total اضافه کرده سر آخر هم با متد gettotal مقدارش رو برگردونده .

به این حرکت میگن کپسوله سازی که نمی تونه total رو یک راست مقدار دهی کنه ...



2. انتزاع: مثلا یک کلاس والد داریم که یه سری توابع داره و کلاس های فرزند که این ها هم یک سری تابع دارن به نام همون تابع والد ولی کار های متفوتی انجام میدن به مثال زیر دقت کنید :



class Book
{ public:
Book(char* s) { name = new char[strlen(s+1)];
strcpy(name, s);
}
void print() { cout << "Here is a book with
name " << name << ".\n";
}
protected:
char* name;
};

class Ebook : public Book
{


public:
Ebook(char* s, float g) : Book(s), size(g) {}
void print() { cout << "Here is an Ebook with name "
<< name << " and size "
<< size << " MB.\n";
}


private:
float size;
}




class Notebook : public Book
{
public:
Notebook(char* s, int n) : Book(s) , pages(n) {}
void print() { cout << "Here is a Notebook with name "
<< name << " and " << pages
<< " pages.\n";
}
private:


int pages;
};


int main()
{ Book* b;
Book mybook("C++‎‎‎‎‎‎");
b = &mybook;
b->print();
Ebook myebook("C#‎‎‎‎‎‎", 5.16);
b = &myebook;
b->print();
Notebook mynotebook(".NET", 230);
b = &mynotebook;

b->print();
}








خروجی :

++Here is a book with name C
#Here is a book with name C
Here is a book with name .NET

با توجه به خروجی ما همچین چیزی انتظار نداشتیم ... ! باید توابع کلاس هایی که ارجاع داده ایم فراخونی بشن در صورتی که هر 3 بار تابع کلاس والد اجرا میشه.

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


class Book
{ public:
Book(char* s) { name = new char[strlen(s+1)];
strcpy(name, s);
}
virtual void print() { cout << "Here is a book with
name " << name << ".\n";
}
protected:
char* name;
};



خروجی جدید :

++Here is a book with name C
Here is an Ebook with name C#‎‎‎‎‎‎ and size 5.16 MB
Here is a Notebook with name .NET and pages 230


به این حرکتی که زدیم میگن ایجاد یک متد به صورت انتزاعی ... مثال انتزاع از کتاب دکتر احمد فراهانی بود .

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

موفق باشید .