۳۰ شهریور ۱۴۰۳

Techboy

اخبار و اطلاعات روز تکنولوژی

مقدمه ای برای OOP: سبک برنامه نویسی روزمره

در اینجا چیزی است که شما باید در مورد برنامه نویسی شی گرا با کلاس ها، متدها، اشیاء و رابط ها با مثال هایی در جاوا، پایتون و TypeScript بدانید.

در اینجا چیزی است که شما باید در مورد برنامه نویسی شی گرا با کلاس ها، متدها، اشیاء و رابط ها با مثال هایی در جاوا، پایتون و TypeScript بدانید.

برنامه نویسی شی گرا (OOP) گاهی اوقات دشوار و ترسناک به تصویر کشیده می شود. حقیقت این است که برنامه نویسی شی گرا از یک مدل بسیار آشنا برای کمک به مدیریت آسان برنامه ها استفاده می کند. بیایید نگاهی دیگر بیندازیم تا ببینیم درک این سبک برنامه‌نویسی بسیار محبوب و تأثیرگذار چقدر آسان است.

اشیاء آشنا هستند

در زندگی روزمره، ما با اشیاء در جهان تعامل داریم. علاوه بر این، ما اشیاء فردی را به عنوان دارای ویژگی های تعیین کننده می شناسیم. سگ روی مبل دارای ویژگی هایی مانند رنگ و نژاد است. در برنامه نویسی، این ویژگی ها را ویژگی ها می نامیم. در اینجا نحوه ایجاد یک شی برای نشان دادن یک سگ و رنگ و نژاد آن در جاوا اسکریپت آمده است:


let dog = { 
  color: “cream”,
  breed: “shih tzu”
}

متغیر dog یک شی با دو ویژگی color و breed است. ما در حال حاضر در حوزه برنامه نویسی شی گرا هستیم. ما می‌توانیم با استفاده از عملگر نقطه به یک ویژگی در جاوا اسکریپت دسترسی پیدا کنیم: dog.color.

کلمه فانتزی: کپسولاسیون

در نمونه کد بالا می توانید ببینید که چگونه شی dog همه ویژگی ها را با هم نگه می دارد. در برنامه نویسی شی گرا، یک کلمه جالب برای این وجود دارد: encapsulation. مانند یک کپسول ویتامین، جسم همه چیز را با هم در یک ظرف نگه می دارد.

ایجاد کلاس‌های اشیا

به زودی کپسولاسیون را به شکل قوی‌تر بازبینی خواهیم کرد. در حال حاضر، بیایید به محدودیت های شی سگ خود فکر کنیم. بزرگترین مشکلی که ما با آن روبرو هستیم این است که هر زمان که بخواهیم یک شی dog جدید بسازیم، باید یک متغیر dog جدید بنویسیم. اغلب، ما نیاز به ایجاد بسیاری از اشیاء از یک نوع داریم. در جاوا اسکریپت و بسیاری از زبان های برنامه نویسی دیگر می توانیم از یک کلاس برای این منظور استفاده کنیم. در اینجا نحوه ایجاد کلاس Dog در جاوا اسکریپت آمده است:


class Dog { 
  color; 
  breed; 
}

کلمه کلیدی class به معنای “کلاسی از اشیاء” است. هر نمونه کلاس یک شی است. کلاس مشخصه های عمومی را که همه نمونه های آن خواهند داشت، تعریف می کند. در جاوا اسکریپت، می‌توانیم یک نمونه از کلاس Dog ایجاد کنیم و از ویژگی‌های آن مانند این استفاده کنیم:


let suki = new Dog();
suki.color = "cream"
console.log(suki.color); // outputs “cream”

کلاس‌ها متداول‌ترین روش برای تعریف انواع شی هستند و اکثر زبان‌هایی که از اشیاء استفاده می‌کنند – از جمله جاوا، پایتون و C++ – از کلاس‌هایی با نحو مشابه پشتیبانی می‌کنند. (جاوا اسکریپت همچنین از نمونه‌های اولیه استفاده می‌کند، که سبک متفاوتی است.) طبق قرارداد، حرف اول نام کلاس بزرگ می‌شود، در حالی که نمونه‌های شی کوچک می‌شوند.

توجه کنید کلاس Dog با کلمه کلیدی new و به عنوان تابعی برای دریافت یک شی جدید فراخوانی می شود. ما اشیاء ایجاد شده به این روش را “نمونه” کلاس می نامیم. شی suki نمونه ای از کلاس Dog است.

کلمه شیک: عضو

در برنامه نویسی شی گرا، ویژگی های یک شی اعضا نامیده می شوند.

افزودن رفتار

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


class Dog { 
  color; 
  breed;
  speak() { 
    console.log(`Barks!`); 
}

اکنون نمونه‌های Dog، وقتی ایجاد می‌شوند، تابعی خواهند داشت که با عملگر نقطه قابل دسترسی است:


set suki = new Dog();
suki.speak() // outputs “Suki barks!”

وضعیت و رفتار

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

معرفی Redwood.js: توسعه سریع برنامه با React

کلمه فانتزی: روش

در برنامه نویسی شی گرا، توابعی که به یک شی تعلق دارند، متد نامیده می شوند. بنابراین اشیا اعضا و روش هایی دارند.

روش های خصوصی و عمومی

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

در برخی از زبان‌ها، مانند جاوا، ما اصلاح‌کننده‌هایی مانند خصوصی و عمومی داریم. یک عضو یا روش private فقط برای سایر متدهای موجود در شی قابل مشاهده است. یک عضو یا روش public در خارج قابل مشاهده است. (همچنین یک اصلاح‌کننده محافظت‌شده وجود دارد که برای قسمت‌های همان بسته قابل مشاهده است.) 

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

دارد


class Dog { 
  #color; 
  #breed;
  speak() { 
    console.log(`Barks!`); 
  }
}

اکنون اگر سعی کنید مستقیماً به ویژگی suki.color دسترسی پیدا کنید، کار نخواهد کرد. این حریم خصوصی کپسوله سازی را قوی تر می کند (یعنی میزان اطلاعات موجود بین بخش های مختلف برنامه را کاهش می دهد).

گیرنده و تنظیم کننده

از آنجایی که اعضا معمولاً در برنامه نویسی شی گرا خصوصی می شوند، اغلب روش های عمومی را می بینید که متغیرهای دریافت و تنظیم:


class Dog { 
  #color; 
  #breed; 
  get color() { 
    return this.#color;  
  } 
  set color(newColor) { 
    this.#color = newColor; 
  }
}

در اینجا ما یک گیرنده و یک تنظیم کننده برای ویژگی color ارائه کرده ایم. بنابراین، اکنون می‌توانیم suki.getColor() را برای دسترسی به رنگ وارد کنیم. این حریم خصوصی متغیر را حفظ می کند و در عین حال امکان دسترسی به آن را فراهم می کند. در دراز مدت، این می تواند به تمیزتر ماندن ساختارهای کد کمک کند. (توجه داشته باشید که گیرنده ها و ستترها را Accessor و Mutator نیز می نامند.)

سازندگان

یکی دیگر از ویژگی های مشترک کلاس های برنامه نویسی شی گرا سازنده است. متوجه می شوید که وقتی یک شی جدید ایجاد می کنیم، new و سپس کلاس را مانند یک تابع فراخوانی می کنیم: new Dog(). کلمه کلیدی new یک شی جدید ایجاد می کند و فراخوانی Dog() در واقع یک متد خاص به نام constructor را فراخوانی می کند. در این مورد، سازنده پیش فرض را فراخوانی می کنیم که هیچ کاری انجام نمی دهد. ما می توانیم سازنده ای مانند این ارائه دهیم:


class Dog { 
  constructor(color, breed) { 
    this.#color = color; 
    this.#breed = breed; 
}
let suki = new Dog(“cream”, “Shih Tzu”);

افزودن سازنده به ما این امکان را می دهد که اشیایی با مقادیر از قبل تنظیم شده ایجاد کنیم. در TypeScript، سازنده constructor نام دارد. در جاوا و جاوا اسکریپت، تابعی با همان نام کلاس است. در پایتون، این تابع __init__ است.

موارد جدید در مایکروسافت دات نت 6

کلید واژه “this”

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

استفاده از اعضای خصوصی

همچنین توجه داشته باشید که می‌توانیم از اعضای خصوصی در داخل کلاس با روش‌های دیگری به جز دریافت‌کننده و تنظیم‌کننده استفاده کنیم:


class Dog { 
  // ... same
  speak() { 
    console.log(`The ${breed} Barks!`); 
  }
}
let suki = new Dog(“cream”, “Shih Tzu”);
suki.speak(); // Outputs “The Shih Tzu Barks!”

OOP به سه زبان

یکی از چیزهای مهم در مورد برنامه نویسی شی گرا این است که به زبان های مختلف ترجمه می شود. اغلب، نحو کاملا مشابه است. فقط برای اثبات آن، در اینجا مثال Dog ما در TypeScript، Java و Python است:


// Typescript
class Dog { 
  private breed: string; 
  constructor(breed: string) { 
    this.breed = breed; 
} 
speak() { console.log(`The ${this.breed} barks!`); } 
} 
let suki = new Dog("Shih Tzu"); 
suki.speak(); // Outputs "The Shih Tzu barks!"

// Java
public class Dog {
    private String breed;

    public Dog(String breed) {
        this.breed = breed;
    }

    public void speak() {
        System.out.println("The " + breed + " barks!");
    }

    public static void main(String[] args) {
        Dog suki = new Dog("cream", "Shih Tzu");
        suki.speak(); // Outputs "The Shih Tzu barks!"
    }
}

// Python
class Dog:
    def __init__(self, breed: str):
        self.breed = breed

    def speak(self):
        print(f"The {self.breed} barks!")

suki = Dog("Shih Tzu")
suki.speak()

ممکن است نحو ناآشنا باشد، اما استفاده از اشیا به عنوان چارچوب مفهومی به شفاف سازی ساختار تقریباً هر زبان برنامه نویسی شی گرا کمک می کند.

انواع فوق العاده و وراثت

کلاس Dog به ما امکان می‌دهد هر تعداد نمونه شی بسازیم. گاهی اوقات، ما می خواهیم نمونه های زیادی ایجاد کنیم که از جهاتی یکسان هستند اما در برخی دیگر متفاوت هستند. برای این کار می توانیم از سوپرتایپ ها استفاده کنیم. در برنامه نویسی شی گرا مبتنی بر کلاس، supertype کلاسی است که کلاس دیگری از آن نشات می گیرد. در OOP-speak، می گوییم زیر کلاس از سوپرکلاس به ارث می برد. ما همچنین می گوییم که یک کلاس توسعه کلاس دیگر است.

جاوا اسکریپت (هنوز) از وراثت مبتنی بر کلاس پشتیبانی نمی‌کند، اما TypeScript پشتیبانی می‌کند، بنابراین بیایید به یک مثال در TypeScript نگاه کنیم.

فرض کنید می‌خواهیم یک سوپرکلاس حیوان با دو زیر کلاس تعریف شده داشته باشیم، Dog و Cat. این کلاس ها از نظر داشتن ویژگی breed مشابه هستند، اما روش speak() متفاوت است زیرا کلاس ها رفتار صحبت متفاوتی دارند:


// Animal superclass
class Animal {
  private breed: string;

  constructor(breed: string) {
    this.breed = breed;
  }

  // Common method for all animals
  speak() {
    console.log(`The ${this.breed} makes a sound.`);
  }
}

// Dog subclass
class Dog extends Animal {
  constructor(breed: string) {
    super(breed); // Call the superclass constructor
  }

  // Override the speak method for dogs
  speak() {
    console.log(`The ${this.breed} barks!`);
  }
}

// Cat subclass
class Cat extends Animal {
  constructor(breed: string) {
    super(breed); // Call the superclass constructor
  }

  // Override the speak method for cats
  speak() {
    console.log(`The ${this.breed} meows!`);
  }
}

// Create instances of Dog and Cat
const suki = new Dog("Shih Tzu");
const whiskers = new Cat("Siamese");

// Call the speak method for each instance
suki.speak(); // Outputs "The Shih Tzu barks!"
whiskers.speak(); // Outputs "The Siamese meows!"

ساده! وراثت فقط به این معنی است که یک نوع دارای تمام خصوصیات نوع مورد نظر است، به جز جایی که من چیزی را متفاوت تعریف کنم.

در برنامه نویسی شی گرا، گاهی اوقات می گوییم که وقتی نوع A نوع B را گسترش می دهد، آن نوع A a-a نوع B است. (در یک لحظه در این مورد بیشتر توضیح می دهیم.)

آنچه توسعه دهندگان نرم افزار باید در مورد طراحی بدانند: مصاحبه با Soleio

مفاهیم وراثت: Overriding، overloading، و polymorphism

در این مثال، دو روش جدید speak() تعریف کرده‌ایم. به این روش اغلب یک روش گفته می شود. شما ویژگی یک سوپرکلاس را با یک ویژگی زیر کلاس به همین نام لغو می کنید. (در برخی از زبان‌ها، می‌توانید با داشتن نام یکسان با آرگومان‌های مختلف، روش‌های overload را نیز انجام دهید. اغراق روش و بارگذاری بیش‌ازحد متفاوت است، اما گاهی اوقات اشتباه می‌شوند زیرا نام‌ها مشابه.)

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

مثلاً تابعی داریم که از مرجع حیوان استفاده می‌کند، سپس می‌توانیم یک نوع فرعی (مانند Cat یا Dog) به تابع ارسال کنیم. . این امکان را برای ایجاد کدهای عمومی تر باز می کند.


function talkToPet(pet: Animal) { 
  pet.speak(); // This will work because speak() is defined in the Animal class 
}

Polymorphism به معنای واقعی کلمه به معنای “شکل های متعدد” است. 

انواع چکیده

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

در اینجا یک نسخه انتزاعی از کلاس Animal (TypeScript) آمده است:


abstract class Animal {
  private breed: string;
  abstract speak(): void;
}

علاوه بر کلمه کلیدی abstract، متوجه خواهید شد که روش انتزاعی speak() پیاده سازی نشده است. مشخص می کند که چه آرگومان هایی را می گیرد (هیچ کدام) و مقدار بازگشتی آن (void). به همین دلیل، نمی‌توانید کلاس‌های انتزاعی را نمونه‌سازی کنید. می توانید به آنها ارجاع دهید یا آنها را گسترش دهید – همین.

همچنین توجه داشته باشید که کلاس Animal انتزاعی ما speak() را پیاده سازی نمی کند، اما ویژگی breed را تعریف می کند. بنابراین، زیر کلاس‌های Animal می‌توانند با کلمه کلیدی super به ویژگی breed دسترسی پیدا کنند که مانند کلمه کلیدی this کار می‌کند. ، اما برای کلاس والد.

رابط ها

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


interface Animal {
  breed: string;
  speak(): void;
}

توجه داشته باشید که ویژگی و روش موجود در این رابط، کلمه کلیدی abstract را اعلام نمی‌کند—می‌دانیم که آنها انتزاعی هستند زیرا بخشی از یک رابط هستند.

انواع انتزاعی و مهندسی بیش از حد

ایده آل انواع انتزاعی این است که تا جایی که می توانید به سوپرتایپ ها فشار دهید، که از استفاده مجدد کد پشتیبانی می کند. در حالت ایده‌آل، ما می‌توانیم سلسله‌مراتبی را تعریف کنیم که به طور طبیعی شامل کلی‌ترین بخش‌های یک مدل در انواع بالاتر هستند، و تنها به تدریج ویژگی‌ها را در انواع پایین‌تر تعریف می‌کنند. (شما می توانید این را در کلاس Object جاوا و جاوا اسکریپت دریافت کنید، که سایرین از آن نزول می کنند و یک متد عمومی toString() را تعریف می کند.)