أهلاً! مثلما أنه من المستحيل تعلم كيفية قيادة الطائرة دون تدريب خاص، لا يمكنك أن تصبح مطور جافا دون قضاء ساعات طويلة في دراسة الأسس النظرية اللازمة. وهذا هو بالضبط ما سنعمل عليه اليوم: سنستمر في استكشاف الأسئلة التي تمت مواجهتها أثناء مقابلات العمل لمطوري Java، وبالطبع، سننظر إلى الإجابات. فيما يلي الجزأين الأول
والثاني من هذه النظرة العامة .
ليس هناك شك في أنه يمكنك أن تصبح مطور Java جيدًا دون كل هذه الأسئلة. ومع ذلك، إذا كان لديك فهم جيد لجميع تعقيدات Java، فستتمتع بالتأكيد بميزة وستبدو أكثر جاذبية في نظر صاحب العمل المستقبلي.
20. ما هي عناصر اللغة التي تمكن التغليف؟
لنتذكر أن التغليف يتعلق بإخفاء تفاصيل تنفيذ الفصل. بمعنى آخر، عندما يتم استخدام فصلنا، فإن مكوناته الداخلية ومنطقه الداخلي لا يكون واضحًا للغرباء. وما هي عناصر اللغة المسؤولة عن ذلك؟ معدّلات الوصول ، بالطبع! أي شيء نريد إخفاءه، نضع علامة عليه باستخدام المُعدِّل الخاص . على سبيل المثال، الحقول الخاصة للفصل الدراسي أو بعض الأساليب الداخلية التي تساعد في تنفيذ بعض الوظائف الداخلية. وبالنسبة لأي شيء نريد توفير الوصول الخارجي إليه، فإننا نضيف معدل الوصول العام . على سبيل المثال، طريقة تنفذ بعض الوظائف (التي قد تستخدم العديد من الطرق الخاصة داخليًا) أو، بالطبع، الحروف والمحددات للوصول إلى الحقول الخاصة للفصل الدراسي. لم نذكر بعد المعدلات الافتراضية والمحمية ، والتي يمكن استخدامها بشكل أكثر مرونة وتخصيص الوصول إلى أجزاء فئة معينة على وجه التحديد .21. ما هي عناصر اللغة التي تمكن من الوراثة؟
الميراث هو آلية تسمح لك بإنشاء فئات بناءً على فئة أخرى. تحتوي Java على الكلمة الأساسية الممتدة لهذا الغرض. على سبيل المثال، لنفترض أن لدينا فئة Cat ، ونريد إنشاء فئة تابعة للأسد . في الكود، سوف يبدو مثل هذا:public class Lion extends Cat
وهذا يعني أن فئة الأسد ترث جميع أساليب ومتغيرات فئة Cat ، باستثناء المتغيرات الثابتة. عنصر آخر من عناصر اللغة المسؤولة عن الميراث هو السوبر . وهو مرجع مشابه لهذا . تشير الكلمة الأساسية this إلى الكائن الذي تمت الإشارة إليه فيه. تشير الكلمة الأساسية super إلى أصل الكائن الحالي. عادةً ما يتم استخدام السوبر :
-
لاستدعاء منشئ الطبقة المتفوقة. على سبيل المثال، تحتوي فئة Cat على متغير اسم داخلي يجب تهيئته في المُنشئ. في مُنشئ فئة Lion ، سيبدو الأمر كما يلي:
public Lion(final String name) { super(name); }
-
للإشارة إلى مجالات وأساليب الأصل. على سبيل المثال، في فئة Cat ، لدينا حقل عمر تمت تهيئته :
public class Cat { int age = 10;
public class Lion extends Cat {
int age = 15;
وإذا أردنا في كائن Lion الإشارة إلى متغير العمر للكائن الأصلي، فعلينا القيام بذلك من خلال super :
super.name
22. ما هي عناصر اللغة المسؤولة عن تعدد الأشكال؟
تعدد الأشكال هو قدرة كائن بتوقيع واحد على اتخاذ أشكال عديدة (العديد من التطبيقات). يمكننا أن نقول بثقة أن الكلمات الرئيسية التي تنفذها Java وتوسعها هي المسؤولة عن تعدد الأشكال. عندما يكون لدينا واجهة، تتيح لنا التطبيقات توفير تطبيق واحد محتمل، ولكن لا يجب أن يكون هذا هو التنفيذ الوحيد، أليس كذلك؟ دعنا نعيد النظر في كيفية استخدام الأدوات :public class Cat implements Animal
ثم في فئة Cat ، يتعين علينا تنفيذ جميع الأساليب المجردة في واجهة الحيوان . الوراثة أيضًا: في الفصل الفرعي، يمكننا تجاوز التنفيذ الحالي للطريقة. هذا يعني أنه مع وجود فئات فرعية متعددة، يمكن أن يكون لدينا عدة تجاوزات مختلفة لنفس الطريقة. أو يمكن أن تكون الطبقة الفائقة مجردة ولها طريقة معينة يجب تنفيذها بطريقة خاصة في كل فئة من فئاتها الفرعية. بمعنى آخر، سيكون لهذه الطريقة العديد من التطبيقات المختلفة. يمكن أن يساعدنا التعليق التوضيحيOverride أيضًا في ذلك . يتم وضعه فوق الأساليب المنفذة ويشير إلى أننا نريد تنفيذ أو تجاوز (إذا كان التنفيذ موجودًا بالفعل في الفئة الفائقة) طريقة معينة للفئة الفائقة أو الواجهة. إنه اختياري ويساعد على اكتشاف الأخطاء بسهولة أكبر. يمكنك استخدام هذا التعليق التوضيحي لإخبار المترجم أنك تريد تجاوز/تنفيذ طريقة الطبقة الفائقة/الواجهة. سيتأكد المترجم بعد ذلك من عدم ارتكاب أخطاء في توقيع الطريقة.
23. ما هو الصلب؟ تقديم أمثلة
SOLID هو اختصار لمبادئ تصميم OOP الخمسة الأساسية لروبرت مارتن. S (مبدأ المسؤولية الفردية) : ينص على أن الفصل يجب أن يكون له غرض/مسؤولية واحدة فقط. بمعنى آخر، لا ينبغي عليك إنشاء فصول تقوم بكل شيء. إذا قمت بذلك، فيمكنك إعادة إنتاج النمط المضاد لـ "كائن الإله". إذا كان لديك كائن Cat ، فيجب أن يحتوي على طرق فقط للتفاعل مع وظائفه الداخلية، ولكن يجب ألا يحتوي على أي منطق عمل لا علاقة له بهذا المثيل. على سبيل المثال، بعض الآليات لتخزين الكائنات من هذا النوع. يجب نقل هذه الوظيفة (خارج كيان Cat ) إلى فئات أو خدمات أخرى، تتمثل مهمتها في توفير منطق الأعمال للكائنات المقابلة. O (مبدأ مفتوح ومغلق) : يوصف هذا المبدأ على النحو التالي: يجب أن تكون الكيانات البرمجية (الفئات، الوحدات، الوظائف، وما إلى ذلك) مفتوحة للتوسيع ولكنها مغلقة للتعديل. على سبيل المثال، لنفترض أننا بحاجة إلى وظيفة مشابهة لوظيفة فئة Cat الموجودة لدينا ولكنها تختلف قليلاً عنها . بدلاً من تغيير وظيفة فئة Cat وبالتالي كسر التعليمات البرمجية في كل مكان يتم استخدامه بالفعل، يمكننا استخدام الميراث أو التركيب . وبذلك نحقق هدفنا المتمثل في تعديل وظيفة فئة Cat ، ونقوم بذلك دون تغيير الفئة نفسها ودون كسر أي شيء. L (مبدأ الاستبدال ليسكوف) : هذا هو مبدأ الاستبدال لباربرا ليسكوف. ينص المبدأ على أن الوظيفة التي تأخذ نوعًا أساسيًا يجب أن تكون قادرة على استخدام الأنواع الفرعية من هذا النوع الأساسي دون معرفة ما يحدث. على سبيل المثال، يجب أن تكون فئة Cat قابلة للاستبدال بأي من أحفادها، على سبيل المثال، الأسد ، دون تغيير سلوكها بشكل أساسي. يظل المنطق العام (السلوك) كما هو، لكن تفاصيل تنفيذ وظائف معينة تتغير. I (مبدأ فصل الواجهة) : ينص هذا المبدأ على أنه من الأفضل أن يكون لديك العديد من الواجهات المتخصصة (مركزة بشكل ضيق) بدلاً من واجهة عالمية واحدة. على سبيل المثال، لنفترض أن أحد المطورين يقوم بتنفيذ بعض الواجهة. إنهم يحتاجون فقط إلى إحدى طرقها، لكن الواجهة بها تسع طرق أخرى لا تتعلق بمنطق الطريقة المطلوبة. في هذه الحالة، سيحتاج المطور إلى تنفيذ عشر طرق للواجهة، تسع منها غير ضرورية بالنسبة لهم! بدلاً من ذلك، من الأفضل إنشاء عشر واجهات مختلفة يمكنك تنفيذها حسب الحاجة. حسنًا، إن لم يكن عشرة، فالعديد منها، ولكل منها أساليب ترتبط ارتباطًا وثيقًا بالغرض الوحيد للواجهة. D (مبدأ انعكاس التبعية): ينص المبدأ على أن الوحدات ذات المستوى الأعلى لا ينبغي أن تعتمد على الوحدات ذات المستوى الأدنى. ينص هذا المبدأ أيضًا على أن "التجريد لا ينبغي أن يعتمد على التفاصيل. التفاصيل يجب أن تعتمد على التجريدات". يجب أن نبني منطقنا من خلال الإشارة إلى الواجهات وتمرير كائنات محددة من الفئات التي تنفذ الواجهة المطلوبة. على سبيل المثال، لنفترض أن لدينا واجهة Cat وبعض التطبيقات، على سبيل المثال، Lion و HouseCat . نحن نبني منطقنا خصيصًا للتفاعل مع واجهة Cat . نقوم بعد ذلك فقط باستبدال الواجهة بتطبيق محدد ( Lion أو HouseCat )، ولكن ليس العكس.24. ما هي الفئة والكائن والواجهة؟
سوف نتذكر أن Java هي لغة OOP. أي أن برامج Java مبنية على التفاعلات بين الكائنات. البرنامج يشبه عش النمل، حيث كل نملة هي كائن. الكائنات عبارة عن مجموعات من البيانات تتضمن طرقًا (وظائف) مختلفة للتفاعل مع هذه البيانات الداخلية. الفصول هي تعليمات أو قوالب لإنشاء الكائنات. هذا يعني أنه يمكن أن يكون لدينا العديد من الكائنات المبنية وفقًا لنفس التعليمات ولكن مملوءة ببيانات مختلفة (أو نفس البيانات). بأخذ مثال من الحياة الواقعية، يمكننا القول أن الفصل هو مخطط لمبنى، والكائن هو مبنى تم تشييده خصيصًا وفقًا للمخطط. تشبه الواجهات الفئات، لكن لا يمكننا استخدامها لإنشاء كائنات. والغرض منها هو إضافة التجريد إلى جافا. وبتعبير أدق، فإنها تضيف مرونة إلى العلاقة بين الفئات والأشياء. ونعني بالمرونة تعدد الأشكال والتجريد الموصوف سابقًا، مما يخلق العديد من الفرص لبناء البنية الداخلية للتطبيق.25. ما هي فئة POJO؟ أعط مثالا على مثل هذه الفئة
POJO (كائن Java قديم عادي) هو كائن فئة بسيط لا يرث من أي فئة محددة ولا ينفذ أي واجهات خدمة تتجاوز تلك المطلوبة لنموذج الأعمال. بمعنى آخر، فئة POJO هي مجرد فئة بدون متطلبات خاصة. الشرط الوحيد هو عدم وجود أجراس وصفارات مختلفة مرتبطة بإطار محدد. كقاعدة عامة، لا ترث هذه الفئات فئات أخرى (باستثناء فئات POJO في نفس الحزمة)، ولا تنفذ واجهات (في بعض الأحيان يتم إجراء استثناء لواجهات العلامات من المكتبة القياسية مثل Serializable أو Cloneable )، ولا تستخدم التعليقات التوضيحية ولا تعتمد على مكتبات الطرف الثالث. دعونا نلاحظ أن POJO يمكن أن يحتوي على أساليب تحتوي على منطق الأعمال والمنشئات من أي نوع. إذا سمحنا بالتعليقات التوضيحية التي لا تغير دلالات الفئة (أي التعليقات التوضيحية التي لا يغير غيابها غرض الكائن أو منطقه)، فيمكن أن تتضمن POJO أيضًا كيانات JPA وكائنات DTO التي تم إلغاء تسلسلها من XML أو JSON ، والتي تكون قواعدها هي المحددة في التعليقات التوضيحية. شيء آخر يجب أخذه في الاعتبار فيما يتعلق بفئات POJO هو أنه من الجيد تجاوز أساليب يساويها و hashCode لأن هذا يمكن أن يساعدها على أداء دورها بشكل أفضل. مثال لفئة POJO :public class User {
private Long id;
private String firstName;
private String lastName;
private Long age;
public User(final Long id, final String firstName, final String lastName, final long age) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
public Long getId() {
return this.id;
}
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
public Long getAge() {
return this.age;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || this.getClass() != o.getClass()) return false;
final User user = (User) o;
return Objects.equals(this.id, user.id) &&
Objects.equals(this.firstName, user.firstName) &&
Objects.equals(this.lastName, user.lastName) &&
Objects.equals(this.age, user.age);
}
@Override
public int hashCode() {
return Objects.hash(this.id, this.firstName, this.lastName, this.age);
}
}
26. ما هي العناصر التي يمكن أن يحتويها الفصل؟
يمكن أن يحتوي الفصل على العناصر التالية:- حقول المثيل؛
- الحقول الثابتة؛
- كتلة التهيئة؛
- كتلة التهيئة الثابتة؛
- المنشئون (يتم دائمًا الإعلان عن المنشئ الفارغ افتراضيًا) ؛
- طُرق؛
- طرق ثابتة
- الشروح المختلفة (التي يمكن تطبيقها على الفصل نفسه أو الأجزاء المكونة له)؛
- الأدوية الجنيسة ؛
- وراثة الفئات الأخرى ( الامتدادات ) أو تطبيقات الواجهات ( التنفيذات ).
27. أخبرنا عن الميراث في جاوة. ما هي تفاصيل الكلمة الرئيسية الفائقة؟
لقد تحدثت سابقًا عن الميراث والكلمة الأساسية الفائقة في Java. وسأذكر بعض النقاط الأكثر أهمية:- يمكننا أن نرث فئة واحدة فقط: ليس لدى Java وراثة متعددة في Java. مع ظهور الأساليب الافتراضية في Java 8، سيصبح هذا البيان مثيرًا للجدل للغاية.
- يتم أيضًا توريث الأساليب والمجالات الخاصة. ببساطة لا يمكن الوصول إليها من الفئة الفرعية (ولكن إذا كان لدينا، على سبيل المثال، حقل خاص ولدينا حروف ومحددات عامة أو محمية ، فيمكننا استخدامها للوصول إلى الحقل).
- لا يمكن وراثة الفئات النهائية .
- لا يمكن تجاوز الأساليب النهائية (ولكن يمكن توريثها وتحميلها بشكل زائد).
- لا يتم توريث الأساليب والمتغيرات الثابتة (لأنها مرتبطة بالفئات وليس بالكائنات).
- عند وراثة الفئات المجردة، يجب تنفيذ أساليبها المجردة، أو يجب أيضًا إعلان الفئة الفرعية مجردة.
- إذا كانت هناك مُنشئات غير افتراضية في الأصل، فيجب تجاوزها في الفصل الفرعي (ولكن لم يتم كتابة @Override فوقها).
- يمكنك توسيع معدّل الوصول ليشمل الأساليب التي تم تجاوزها في الفئة الفرعية: خاص -> افتراضي -> محمي -> عام . يمكن للطرق التي تم تجاوزها في الفئة الفرعية طرح استثناءات أضيق، على سبيل المثال: استثناء -> IOException -> FileNotFoundException.
28. ما هي التوقيعات الأسلوبية؟ تقديم أمثلة على التوقيعات الصحيحة وغير الصحيحة
توقيع الطريقة هو اسم الطريقة بالإضافة إلى أنواع معلمات الإدخال (ترتيب المعلمات مهم). لا يتضمن توقيع الطريقة القيمة المرجعة أو الاستثناءات التي تطرحها الطريقة. مثال على التوقيع الصحيح:doSomething(int, double, double)
مثال على توقيع غير صحيح:
void doSomething(int firstArg, int secondArg) throws Exception
يُطلق على توقيع الطريقة، جنبًا إلى جنب مع نوع الإرجاع وقائمة الاستثناءات التي تم طرحها، اسم عقد الطريقة . هذا كل شيء لهذا اليوم! أراك لاحقًا!
GO TO FULL VERSION