مبادئ OOP

نشرت في المجموعة
Java هي لغة موجهة للكائنات. هذا يعني أنك بحاجة إلى كتابة برامج Java باستخدام أسلوب موجه للكائنات. ويعتمد هذا الأسلوب على استخدام الكائنات والفئات في البرنامج.

المبادئ الأساسية لـ OOP:

مبادئ OOP - 1دعونا نحاول، بمساعدة الأمثلة، فهم ما هي الفئات والكائنات، وكذلك كيفية تطبيق المبادئ الأساسية لـ OOP في الممارسة العملية: التجريد والميراث وتعدد الأشكال والتغليف.

ما هو الكائن؟

العالم الذي نعيش فيه يتكون من أشياء. إذا نظرنا حولنا، فسنرى أننا محاطون بالمنازل والأشجار والسيارات والأثاث والأطباق وأجهزة الكمبيوتر. كل هذه العناصر هي كائنات، ولكل منها مجموعة من الخصائص والسلوك والغرض المحدد. لقد اعتدنا على الأشياء، ونستخدمها دائمًا لأغراض محددة جدًا. على سبيل المثال، إذا أردنا الذهاب إلى العمل، نستخدم السيارة، وإذا أردنا تناول الطعام، نستخدم الأطباق، وإذا كنا بحاجة إلى الاسترخاء، نحتاج إلى أريكة مريحة. اعتاد الإنسان على التفكير بموضوعية لحل مشاكل الحياة اليومية. وكان هذا أحد أسباب استخدام الكائنات في البرمجة، وهذا الأسلوب في إنشاء البرامج كان يسمى بالكائنات الموجهة. دعونا نعطي مثالا. تخيل أنك قمت بتطوير طراز هاتف جديد وترغب في إطلاق إنتاجه الضخم. باعتبارك مصممًا للهاتف، فأنت تعرف الغرض منه، وكيف سيعمل، وما هي الأجزاء التي سيتكون منها (الحافظة، والميكروفون، ومكبر الصوت، والأسلاك، والأزرار، وما إلى ذلك). ومع ذلك، أنت فقط تعرف كيفية توصيل هذه الأجزاء. ومع ذلك، فأنت لا تخطط لإنتاج الهواتف شخصيًا، ولهذا لديك طاقم كامل من الموظفين. حتى لا تضطر في كل مرة إلى شرح كيفية توصيل أجزاء الهاتف، وحتى تصبح جميع الهواتف في الإنتاج متماثلة، قبل البدء في إنتاجها، ستحتاج إلى عمل رسم على شكل وصف هيكل الهاتف. في OOP، يُطلق على هذا الوصف أو الرسم أو الرسم التخطيطي أو القالب فئة يتم إنشاء كائن منها عند تنفيذ البرنامج. الفئة هي وصف لكائن لم يتم إنشاؤه بعد، مثل القالب العام الذي يتكون من الحقول والأساليب والمنشئ، والكائن هو مثيل لفئة تم إنشاؤها على أساس هذا الوصف.

تجريد OOP

دعونا نفكر الآن في كيفية الانتقال من كائن في العالم الحقيقي إلى كائن في برنامج، باستخدام الهاتف كمثال. يتجاوز تاريخ وسيلة الاتصال هذه 100 عام، ويعد الهاتف الحديث، على عكس سابقه من القرن التاسع عشر، جهازًا أكثر تعقيدًا. عندما نستخدم الهاتف، فإننا لا نفكر في بنيته والعمليات التي تحدث بداخله. نحن ببساطة نستخدم الوظائف التي يوفرها مطورو الهاتف - الأزرار أو شاشة اللمس لتحديد رقم وإجراء المكالمات. كانت إحدى واجهات الهاتف الأولى عبارة عن مقبض يتم تشغيله لإجراء مكالمة. وبطبيعة الحال، لم يكن هذا مريحا للغاية. ومع ذلك، أدى المقبض وظيفته بشكل صحيح. إذا نظرت إلى الهاتف الأكثر حداثة والأول، فيمكنك على الفور التعرف على أهم التفاصيل المهمة لكل من الجهاز من أواخر القرن التاسع عشر والهاتف الذكي فائق الحداثة. هذا هو إجراء مكالمة (طلب رقم) واستقبال مكالمة. هذا هو ما يجعل الهاتف هاتفًا وليس شيئًا آخر. لقد قمنا الآن بتطبيق المبدأ في OOP - وهو تسليط الضوء على أهم الخصائص والمعلومات حول كائن ما. يسمى مبدأ OOP هذا بالتجريد. يمكن أيضًا تعريف التجريد في OOP على أنه طريقة لتمثيل عناصر مشكلة العالم الحقيقي ككائنات في البرنامج. يرتبط التجريد دائمًا بتعميم بعض المعلومات حول خصائص الأشياء أو الكائنات، لذا فإن الشيء الرئيسي هو فصل المعلومات المهمة عن المعلومات غير المهمة في سياق المشكلة التي يتم حلها. في هذه الحالة، يمكن أن يكون هناك عدة مستويات من التجريد. دعونا نحاول تطبيق مبدأ التجريد على هواتفنا. أولاً، دعونا نسلط الضوء على أنواع الهواتف الأكثر شيوعًا منذ ظهورها وحتى يومنا هذا. على سبيل المثال، يمكن تمثيلها في شكل رسم تخطيطي موضح في الشكل 1. مبادئ OOP - 2الآن، بمساعدة التجريد، يمكننا تسليط الضوء على معلومات عامة في هذا التسلسل الهرمي للكائنات: نوع مجرد شائع من الكائنات - الهاتف، وهو سمة عامة لـ الهاتف - سنة إنشائه، وواجهة مشتركة - جميع الهواتف قادرة على استقبال وإرسال المكالمات. إليك ما يبدو عليه الأمر في جافا:
public abstract class AbstractPhone {
    private int year;

    public AbstractPhone(int year) {
        this.year = year;
    }
    public abstract void call(int outputNumber);
    public abstract void ring (int inputNumber);
}
بناءً على هذه الفئة المجردة، سنكون قادرين على إنشاء أنواع جديدة من الهواتف في البرنامج باستخدام مبادئ Java OOP الأساسية الأخرى، والتي سننظر فيها أدناه.

التغليف

بمساعدة التجريد، نسلط الضوء على ما هو مشترك بين جميع الكائنات. ومع ذلك، فإن كل طراز هاتف فردي ومختلف إلى حد ما عن الآخرين. كيف يمكننا رسم الحدود في البرنامج وتحديد هذه الفردية؟ كيف يمكننا التأكد من عدم تمكن أي من المستخدمين من كسر هاتفنا عن طريق الخطأ أو عن قصد، أو محاولة تحويل طراز إلى آخر؟ بالنسبة لعالم الأشياء الحقيقية، الإجابة واضحة: تحتاج إلى وضع جميع الأجزاء في جسم الهاتف. بعد كل شيء، إذا لم نفعل ذلك وتركنا كل الأجزاء الداخلية للهاتف والأسلاك التي تربطها بالخارج، فسيكون هناك بالتأكيد مجرب فضولي يريد "تحسين" تشغيل هاتفنا. لتجنب مثل هذا التدخل في تصميم الكائن وتشغيله، يستخدم OOP مبدأ التغليف - وهو مبدأ أساسي آخر لـ OOP، حيث يتم دمج سمات الكائن وسلوكه في فئة واحدة، ويتم إخفاء التنفيذ الداخلي للكائن عن المستخدم، ويتم توفير واجهة مفتوحة للعمل مع الكائن. تتمثل مهمة المبرمج في تحديد السمات والأساليب التي سيتم الوصول إليها بشكل عام وأيها عبارة عن تطبيقات داخلية للكائن ولا ينبغي تعديلها.

التغليف والتحكم في الوصول

لنفترض أنه أثناء الإنتاج، يتم نقش معلومات عنه على ظهر الهاتف: سنة تصنيعه أو شعار الشركة المصنعة. هذه المعلومات تميز هذا النموذج على وجه التحديد - حالته. يمكننا القول أن مطور الهاتف اهتم بثبات هذه المعلومات - فمن غير المرجح أن يفكر أي شخص في إزالة النقش. في عالم Java، يتم وصف حالة الكائنات المستقبلية في فئة باستخدام الحقول، ويتم وصف سلوكها باستخدام الأساليب. يتم تنفيذ القدرة على تغيير الحالة والسلوك باستخدام معدلات الوصول إلى الحقول والطرق - privateو و و (الوصول الافتراضي) protected. على سبيل المثال، قررنا أن سنة الإنشاء واسم الشركة المصنعة للهاتف وإحدى الطرق تنتمي إلى التنفيذ الداخلي للفئة ولا يمكن تغييرها بواسطة كائنات أخرى في البرنامج. باستخدام الكود، يمكن وصف الفصل على النحو التالي: publicdefault
public class SomePhone {

    private int year;
    private String company;
    public SomePhone(int year, String company) {
        this.year = year;
        this.company = company;
    }
private void openConnection(){
    //findComutator
    //openNewConnection...
}
public void call() {
    openConnection();
    System.out.println("I'm calling a number");
}

public void ring() {
    System.out.println("Дзынь-дзынь");
}

 }
يجعل المعدل privateحقول وأساليب الفصل الدراسي متاحة فقط داخل هذا الفصل. وهذا يعني أنه privateلا يمكن الوصول إلى الحقول من الخارج، ولا يمكن privateاستدعاء الأساليب. إن إخفاء الوصول إلى طريقة ما openConnectionيترك لنا أيضًا الفرصة لتغيير التنفيذ الداخلي لهذه الطريقة بحرية، حيث إن هذه الطريقة مضمونة بعدم استخدامها من قبل كائنات أخرى ولن تعطل عملها. للعمل مع كائننا، نترك الطرق مفتوحة callباستخدام ringالمُعدِّل public. يعد توفير الأساليب العامة للعمل مع كائن أيضًا جزءًا من آلية التغليف، لأنه إذا تم رفض الوصول إلى الكائن تمامًا، فسيصبح عديم الفائدة.

ميراث

دعونا نلقي نظرة على مخطط الهاتف مرة أخرى. يمكنك أن ترى أنه يمثل تسلسلًا هرميًا يحتوي فيه النموذج الموجود أدناه على جميع خصائص النماذج الموجودة أعلى الفرع، بالإضافة إلى خصائصه الخاصة. على سبيل المثال، يستخدم الهاتف الذكي شبكة خلوية للاتصال (له خصائص الهاتف الخلوي)، وهو لاسلكي ومحمول (له خصائص الهاتف اللاسلكي)، ويمكنه استقبال وإجراء المكالمات (له خصائص الهاتف). في هذه الحالة، يمكننا أن نتحدث عن وراثة خصائص الكائن. في البرمجة، الميراث هو استخدام الفئات الموجودة لتحديد فئات جديدة. لنلقِ نظرة على مثال لإنشاء فئة للهواتف الذكية باستخدام الميراث. يتم تشغيل جميع الهواتف اللاسلكية بواسطة بطاريات قابلة لإعادة الشحن، والتي لها عمر تشغيلي محدد بالساعات. لذلك دعونا نضيف هذه الخاصية إلى فئة الهواتف اللاسلكية:
public abstract class WirelessPhone extends AbstractPhone {

    private int hour;

    public WirelessPhone(int year, int hour) {
        super(year);
        this.hour = hour;
    }
    }
callترث الهواتف المحمولة خصائص الهاتف اللاسلكي، وأضفنا أيضًا تطبيقًا للطرق والأساليب لهذه الفئة ring:
public class CellPhone extends WirelessPhone {
    public CellPhone(int year, int hour) {
        super(year, hour);
    }

    @Override
    public void call(int outputNumber) {
        System.out.println("Calling a number" + outputNumber);
    }

    @Override
    public void ring(int inputNumber) {
        System.out.println("A subscriber is calling you" + inputNumber);
    }
}
وأخيرا، فئة الهواتف الذكية، والتي، على عكس الهواتف المحمولة الكلاسيكية، لديها نظام تشغيل كامل. يمكنك إضافة برامج جديدة يدعمها نظام التشغيل هذا إلى هاتفك الذكي، وبالتالي توسيع وظائفه. باستخدام الكود، يمكن وصف الفصل على النحو التالي:
public class Smartphone extends CellPhone {

    private String operationSystem;

    public Smartphone(int year, int hour, String operationSystem) {
        super(year, hour);
        this.operationSystem = operationSystem;
    }
public void install(String program){
    System.out.println("Installing" + program + "For" + operationSystem);
}

}
كما ترون، Smartphoneقمنا بإنشاء القليل جدًا من التعليمات البرمجية الجديدة لوصف الفصل، لكننا حصلنا على فصل جديد بوظائف جديدة. يمكن أن يؤدي استخدام مبدأ وراثة OOP إلى تقليل كمية التعليمات البرمجية بشكل كبير، وبالتالي تسهيل عمل المبرمج.

تعدد الأشكال

إذا نظرنا إلى جميع طرازات الهواتف، فبالرغم من الاختلافات في مظهر وتصميم النماذج، يمكننا تحديد بعض السلوكيات الشائعة فيها - حيث يمكنها جميعها استقبال وإجراء المكالمات ولديها مجموعة واضحة وبسيطة من أزرار التحكم. بتطبيق أحد المبادئ الأساسية لـ OOP، والمعروف لنا بالفعل، وهو التجريد في مصطلحات البرمجة، يمكننا القول أن كائن الهاتف له واجهة مشتركة واحدة. لذلك، يمكن لمستخدمي الهاتف استخدام نماذج مختلفة بشكل مريح باستخدام نفس أزرار التحكم (الميكانيكية أو التي تعمل باللمس)، دون الخوض في التفاصيل الفنية للجهاز. لذلك، أنت تستخدم الهاتف الخليوي باستمرار، ويمكنك بسهولة إجراء مكالمة من نظيره الثابت. المبدأ في OOP عندما يتمكن البرنامج من استخدام كائنات لها نفس الواجهة دون معلومات حول البنية الداخلية للكائن يسمى تعدد الأشكال . لنتخيل أننا نحتاج في برنامجنا إلى وصف مستخدم يمكنه استخدام أي طراز هاتف للاتصال بمستخدم آخر. هيريس كيفية القيام بذلك:
public class User {
    private String name;

    public User(String name) {
        this.name = name;
            }

    public void callAnotherUser(int number, AbstractPhone phone){
// here it is polymorphism - using the abstract type AbstractPhone phone in the code!
        phone.call(number);
    }
}
 }
الآن دعونا نصف نماذج الهواتف المختلفة. أحد موديلات الهواتف الأولى:
public class ThomasEdisonPhone extends AbstractPhone {

public ThomasEdisonPhone(int year) {
    super(year);
}
    @Override
    public void call(int outputNumber) {
        System.out.println("Turn the Handle");
        System.out.println("Give me the phone number, sir");
    }

    @Override
    public void ring(int inputNumber) {
        System.out.println("Phone calls");
    }
}
الهاتف الثابت العادي:
public class Phone extends AbstractPhone {

    public Phone(int year) {
        super(year);
    }

    @Override
    public void call(int outputNumber) {
        System.out.println("I'm calling a number" + outputNumber);
    }

    @Override
    public void ring(int inputNumber) {
        System.out.println("Phone calls");
    }
}
وأخيرًا، هاتف فيديو رائع:
public class VideoPhone extends AbstractPhone {

    public VideoPhone(int year) {
        super(year);
    }
    @Override
    public void call(int outputNumber) {
        System.out.println("I connect a video channel for the subscriber" + outputNumber );
    }
    @Override
    public void ring(int inputNumber) {
        System.out.println("You have an incoming video call..." + inputNumber);
    }
  }
لنقم بإنشاء كائنات في الطريقة main()واختبار الطريقة callAnotherUser:
AbstractPhone firstPhone = new ThomasEdisonPhone(1879);
AbstractPhone phone = new Phone(1984);
AbstractPhone videoPhone=new VideoPhone(2018);
User user = new User("Andrey");
user.callAnotherUser(224466,firstPhone);
// Rotate the knob
// Tell me the number of the subscriber, sir
user.callAnotherUser(224466,phone);
//Call number 224466
user.callAnotherUser(224466,videoPhone);
//I connect the video channel for subscriber 224466
من خلال استدعاء نفس الأسلوب على الكائن user، حصلنا على نتائج مختلفة. تم اختيار تطبيق طريقة معينة callضمن الطريقة callAnotherUserديناميكيًا بناءً على النوع المحدد لكائن الاستدعاء أثناء تنفيذ البرنامج. هذه هي الميزة الرئيسية لتعدد الأشكال - اختيار التنفيذ أثناء تنفيذ البرنامج. في أمثلة فئة الهاتف أعلاه، استخدمنا تجاوز الطريقة، وهي تقنية تغير تنفيذ الطريقة المحددة في الفئة الأساسية دون تغيير توقيع الطريقة. يعد هذا في الأساس بديلاً للأسلوب، وهو الأسلوب الجديد المحدد في الفئة الفرعية الذي يتم استدعاؤه عند تشغيل البرنامج. عادة، عند تجاوز طريقة ما، يتم استخدام التعليق التوضيحي @Override، الذي يخبر المترجم بالتحقق من توقيعات الطرق المتجاوزة والتجاوزية. ونتيجة لذلك ، للتأكد من أن أسلوب برنامجك يتوافق مع مفهوم OOP ومبادئ OOP java، اتبع النصائح التالية:
  • تسليط الضوء على الخصائص الرئيسية للكائن.
  • تسليط الضوء على الخصائص والسلوك المشترك واستخدام الميراث عند إنشاء الكائنات؛
  • استخدام الأنواع المجردة لوصف الكائنات؛
  • حاول دائمًا إخفاء الأساليب والمجالات المتعلقة بالتنفيذ الداخلي للفصل.
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION