شخصياً ، ما يسمى الفصول الدراسية في البرمجة هي نفس مفهوم الفصول في العالم الحقيقي الذي يصنف الأشياء ، لكن يتم استعارتها في البرمجة. تمثل الفصول الأشياء الأشياء التي لديها سلسلة من القواسم المشتركة ونفس العمليات أو الإجراءات ، وهي أنواع بيانات مجردة في البرمجة. كل فرد محدد (في العالم الحقيقي) ومتغيرات المثيل (للبرمجة) هي كائنات.
الفصل هو تمثيل للميزات الشائعة (السمات والعمليات) لبعض الأشياء في العالم الحقيقي ، والكائن هو مثيل للفئة.
سمات الفصل: هل اختصار السمات الثابتة للفئة ، والتي تشير إلى مختلف البيانات الواردة في الفصل ، مثل المتغيرات أو كائنات الفئة الأخرى ؛
خدمة الفصل: تسمى وظيفة العضو أو طريقة.
¨
شكل تعريف الفصل في جافا هو كما يلي:
[modifier] اسم فئة الفئة [تمديد الفئة الأصل] [تنفيذ اسم الواجهة]
لنتحدث عن كل جزء من هذا بالتفصيل:
قبل الكلمة الرئيسية للفصل ، يتم تقسيم معدلات الفئة عمومًا إلى ثلاثة أنواع: معدلات الوصول إلى الطبقة العامة العامة ، المعدل النهائي (محدد الفئة النهائية) والمعدل التجريدي (محدد الفئة التجريدية)
من بينها ، لا يمكن أن يكون معدل الإذن علنيًا أو افتراضيًا فقط (أي فارغ ، لا شيء ، مما يشير إلى أنه يتم تعريفه على أنه ودود) ، والجمهور يعني أنه يمكن استخدام الفصل والوصول إليه في أي مكان (طالما يمكن للبرنامج العثور على موقع الفصل) ، سواء في نفس الحزمة أو في حزم مختلفة. لاحظ أن هذا يختلف عن C ++. ليس لدى C ++ معدل لتقييد حقوق الوصول إلى الفصل ، ولكن لديه حقوق وصول لعلاقات الميراث بين الفصول. بالإضافة إلى ذلك ، لديهم جميعًا حقوق الوصول إلى سمات الطبقة والأساليب. إن إذن الوصول الافتراضي (أي ، المعروف بأنه ودود) يعني أنه لا يمكن الرجوع إليه والوصول إليه فقط بواسطة فئات في نفس الحزمة ، ولكن لا يمكن الوصول إليها والرجوع إليها من قبل الفئات في حزم أخرى ، حتى لو تم استيرادها.
سيتم ذكره أيضًا لاحقًا: عندما يتم استخدام المعدل الافتراضي لسمة فئة وطريقة فئة ، يتم التعبير عن أنه لا يمكن الرجوع إليه إلا من خلال الفئات في نفس الحزمة.
لا يُسمح بالميراث المتعدد في Java ، وهو يختلف عن C ++. من أجل تعويض هذا العيب ، قدمت Java مفهوم الواجهة.
في تعريف الفئة أعلاه ، يحتوي جسم الفئة بشكل أساسي على المحتوى المحدد للفئة ، بما في ذلك سمات الفصل وطرق الفصل. يمكن أن تكون خصائص الفصل متغيرات بسيطة أو حالات من فئات معينة. إذا كان مثيلًا للفصل ، فيمكن تعريفه على النحو التالي:
[modifier] اسم كائن اسم الفئة = اسم فئة جديد (قائمة المعلمة) ؛
عند إعلان الكائنات والمتغيرات المعقدة ، لا يمكنك استخدام الخلق أثناء الإعلانات ، ولكن يمكن إنشاؤها في البنائين المستقبليين.
عادةً ما تلعب الطرق المحددة في الفصل دورتين: الأول هو إجراء عمليات مختلفة حول سمات الفصل ؛ والآخر هو تنفيذ تبادل البيانات وتسليم الرسائل وغيرها من العمليات مع فئات أو كائنات أخرى.
بناء الجملة لإعلان الأساليب في جافا هو كما يلي:
[Modifier] اسم طريقة الإرجاع اسم الطريقة (قائمة المعلمة) بإلقاء اسم الاستثناء 1 ، اسم الاستثناء 2 ، ... {الطريقة الجسم: إعلان متغير محلي ؛ تسلسل البيان ؛}يتم استخدام طرق الفصل ، والمعروفة أيضًا باسم وظائف الأعضاء ، لتحديد العمليات على سمات الفصل وتنفيذ الوظائف الداخلية للفئات. كما أنها نافذة مهمة للفصول للتفاعل مع العالم الخارجي.
يركز مبرمبو Java على إنشاء أنواع محددة من قبل المستخدم تسمى الفئات. وتسمى الفصول أيضا أنواع المعرفة المبرمج. يحتوي كل فئة على بيانات ومجموعة من طرق معالجة البيانات. يسمى جزء البيانات في الفصل متغيرات المثيل. يسمى مثيل لنوع محدد من قبل المستخدم (أي فئة) كائن.
كائن هو مثيل للفئة. الفئة هي تجريد لنفس النوع من الكائن وقالب لإنشاء كائن. سيفتح إنشاء كائن في البرنامج مساحة في الذاكرة ، بما في ذلك خصائص وطرق الكائن. قم بإنشاء كائن باستخدام مشغل الكلمات الرئيسية جديدة.
مُنشئ (يمكن مقارنته بـ C ++ ، وهو ما يشبه C ++ تقريبًا)
قم بإنشاء مُنشئك
• اسم المنشئ واسم الفصل هو نفسه. عند إنشاء كائن من فئة الموظف ، يتم بدء تشغيل هذا المُنشئ ويتم تعيين حقل المثيل قيمة أولية. في Java ، التعريف والتهيئة موحدة - كلاهما لا غنى عنه.
على سبيل المثال ، عند إنشاء مثيل لفئة الموظف مع الكود التالي ،
Newemployee ("James Bond" ، 100000،1950،1،1) ؛
خصائص المنشئ هي:
(1) المُنشئ والفئة لهما نفس الاسم.
(2) يمكن للفصل أن يكون لها عدة مُنشئين.
(3) يمكن أن يكون للمنشئ 0 أو 1 أو أكثر من المعلمات.
(4) لا يوجد لدى المُنشئ قيمة إرجاع.
(5) يتم استدعاء المُنشئ دائمًا مع المشغل الجديد.
دور المنشئ
(1) تهيئة الكائن
(2) إدخال مزيد من المرونة (مهمة متغيرة أو عمليات أكثر تعقيدًا)
(3) لا يمكن تعريف المنشئ في جافا
لا يمكن تحديد مُنشئ في Java ، وسيقوم النظام تلقائيًا بإنشاء مُنشئ افتراضي للنظام. اسم هذا المُنشئ هو نفس اسم الفصل ، ولا يحتوي على معلمات رسمية ولا يؤدي أي عمليات.
نظرة عامة على الطريقة
يتكون برنامج Java من تعريفات الفصل ، والفئة بها جزأين: الخصائص والأساليب. ما هي فئة وصف السمة ، وما هو فئة وصف الطريقة. أي كائن لديه ذاكرة مستقلة لتخزين خصائصه. تشترك جميع كائنات الفصل في الطريقة المخزنة في الذاكرة.
بمعنى آخر: الأساليب هي المكون الرئيسي للفئة. في الفصل ، ينعكس دور البرنامج في الطريقة.
الطريقة هي إنشاء روتين فرعي مسمى بواسطة Java. طريقة رئيسية وعدة أساليب فرعية. تستدعي الطريقة الرئيسية طرقًا أخرى ، ويمكن أيضًا استدعاء طرق أخرى لبعضها البعض ، ويمكن استدعاء نفس الطريقة في أي وقت بواسطة طريقة أو أكثر.
سيؤدي تحديد طريقة أخرى بطريقة واحدة إلى حدوث خطأ في بناء الجملة.
(1) من الأفضل تجنب متغيرات مثيل "قناع" المتغيرات المحلية. يمكن القيام بذلك دون استخدام المعرف الذي يحمل نفس الاسم في الفصل ؛ يتم استخدام المعلمات في مكالمات الطريقة لتمرير القيم والمراجع الرقمية ، ويمكن أيضًا استدعاء الأساليب في متداخلة ومتكررة.
(2) إذا تم تحديد نوع قيمة الإرجاع غير الفاسد في هيئة الطريقة ، فيجب أن تتضمن الطريقة عبارة إرجاع لضمان وجود قيمة إرجاع في أي حال ، ولا يمكن أن يتبع بيان الإرجاع أي تعبير ؛
الهيكل الأساسي لبرامج Java هو كما يلي:
تقديم مكتبة فئة Java ؛ تحديد فئة المستخدم 1 {تحديد عدة متغيرات أو كائنات من الفئة 1: تحديد الطريقة 1 من الفئة 1 ؛ تحديد الطريقة 2 من الفئة 1 ؛ ... تحديد الطريقة M1 من الفئة 1 ؛ } تحديد فئة المستخدم 2 {تحديد عدة متغيرات أو كائنات من الفئة 2: تحديد الطريقة 1 من الفئة 2 ؛ تحديد الطريقة 2 من الفئة 2 ؛ ... تحديد الطريقة M2 من الفئة 2}قدمت Java مفهوم "معدل التحكم في الوصول" الذي يسمح لمبدعي المكتبات بإعلان ما يمكن استخدامه من قبل مبرمجي العملاء وما لا يمكن استخدامه.
هذا المستوى من التحكم في الوصول هو بين نطاق "الحد الأقصى للوصول" و "الحد الأدنى للوصول" ، بما في ذلك: عام ، "افتراضي" (لا توجد كلمة رئيسية) ، محمية وخاصة. تشرح القائمة التالية معنى معدلات التحكم في الوصول:
شخصية التحكم في الوصول العام
للفصول:
لا يوجد سوى وحدة تحكم وصول واحدة لفصل في Java: عام ، أي عام. يتم الإعلان عن الفصل كطبقة عامة ، مما يشير إلى أنه يمكن الوصول إليه والرجوع إليه من قبل جميع الفئات الأخرى. يشير الوصول والمرجع هنا إلى أن الفصل مرئي وقابل للاستخدام ككل. يمكن لأجزاء أخرى من البرنامج إنشاء كائنات من هذه الفئة ، ومتغيرات أعضاء الوصول المرئية داخل الفصل ، واتصل أساليبها المرئية.
يكون الفصل مرئيًا لأجزاء أخرى من البرنامج ككل ، ولا يمثل أن جميع الخصائص والأساليب في الفصل مرئية أيضًا لأجزاء أخرى من البرنامج. السابق هو مجرد شرط ضروري لهذا الأخير. ما إذا كان يمكن الوصول إلى خصائص وطرق الفصل من قبل جميع الفئات الأخرى على أحرف التحكم في الوصول لهذه الخصائص والأساليب.
تستخدم للخصائص في الفصل:
تسمى السمات داخل الفصل المعدلة مع الجمهور السمات العامة. إذا كانت هذه الفئة فئة عامة ، فيمكن الوصول إليها من قبل جميع الفصول الأخرى.
التحكم الافتراضي في الوصول
تستخدم للدروس
إذا لم يكن لدى فئة أحرف التحكم في الوصول ، فهذا يعني أن لديها خصائص التحكم الافتراضية في الوصول. ينص عنصر التحكم الافتراضي على الوصول إلى أنه لا يمكن الوصول إلى الفئة إلا من قبل الفئات في نفس الحزمة ، ولا يمكن استخدامها بواسطة فئات في الحزم الأخرى. تسمى ميزة الوصول هذه إمكانية الوصول إلى الحزمة. من خلال إعلان أحرف التحكم في الوصول للفئة ، يمكن أن تكون بنية البرنامج بأكملها واضحة وصارمة ، مما يقلل من التداخل والأخطاء بين الفئات.
تستخدم لسمات الفصل
إذا كانت الخصائص والأساليب داخل الفصل غير محدودة برموز التحكم في الوصول ، فإنها تشير أيضًا إلى أنها إمكانية الوصول إلى الحزم.
3 شخصية تحكم خاصة في الوصول الخاص
لا يمكن الوصول إلى السمات أو الأساليب المعدلة بالخاصة وتعديلها إلا من خلال الفئة نفسها ، ولا يمكن الحصول عليها والإشارة إليها من قبل أي فئة أخرى ، بما في ذلك الفئات الفرعية للفئة.
1). تحتوي البيانات الخاصة ، على سبيل المثال ، على ثلاثة حقول مثيلات ، تحتوي على بيانات يتم تشغيلها داخل مثيل من فئة الموظف.
اسم السلسلة الخاصة ؛
راتب مزدوج خاص ؛
التاريخ الخاص المستأجر ؛
يتم استخدام الكلمة الرئيسية الخاصة للتأكد من أنه لا يمكن الوصول إلى حقول المثيلات هذه إلا من قبل فئة الموظف نفسها.
2) طريقة خاصة عند تنفيذ الفصل ، نجعل جميع حقول البيانات الخاصة لأن البيانات العامة خطيرة. ما هو الوضع مع الطريقة؟ على الرغم من أن معظم الطرق عامة ، إلا أن الأساليب الخاصة تستخدم أيضًا. لا يمكن فصل هذه الطرق إلا بنفس الطريقة.
باختصار ، يمكن تحديد الطريقة الخاصة في الحالات التالية:
(1) تلك الطرق غير المرتبطة بمستخدم الفصل.
(2) تلك الطرق التي ليس من السهل الحفاظ عليها إذا تم تغيير تنفيذ الفصل.
تحمي شخصية التحكم المحمية في الوصول
يمكن الرجوع إلى متغيرات الأعضاء المعدلة مع المحمية من خلال ثلاثة أنواع: الفئة نفسها ، والفئات الأخرى في نفس الحزمة ، والفئات الفرعية للفئة في حزم أخرى. الغرض الرئيسي من استخدام المعدل المحمي هو السماح لدراساته الفرعية في حزم أخرى للوصول إلى خصائص محددة من الفئة الأصل.
تقدمنا الكلمة الرئيسية المحمية إلى مفهوم يسمى "الميراث" ، والذي يعتمد على الفئات الموجودة ويضيف أعضاء جدد إليها دون التأثير على الفئات الموجودة - نسمي هذه الفئة الأساسية "الفئة الأساسية" أو "الفئة الأساسية". يمكن أن يغير أيضًا سلوك الأعضاء الحاليين في تلك الفئة. للميراث من فئة حالية ، نقول أن صفنا الجديد "يمتد" الفصل الحالي
شخصية تحكم محمية محمية محمية محمية محمية
يتم استخدام خاص ومحمي في التسلسل لتشكيل حرف التحكم الكامل في الوصول: حرف التحكم في الوصول إلى الحماية الخاصة. يمكن الوصول إلى متغيرات الأعضاء المعدلة مع PrivateProtected من قبل فئتين ، والآخر هو الفئة نفسها ، والآخر هو جميع الفئات الفرعية للفئة ، سواء كانت هذه الفئات الفرعية في نفس الحزمة مثل الفئة أو في حزم أخرى.
بالمقارنة مع المحمية ، يستبعد المعدل المحمي الخاص غير النماذج ضمن نفس الحزمة من النطاق الذي يمكن الوصول إليه ، مما يجعل متغيرات الأعضاء أكثر ملكية للصفوف ذات العلاقات الوراثية الصريحة بدلاً من الحزم التي يتم تجميعها بشكل فضفاض معًا.
المعدل الثابت
يسمى ثابت المعدل الثابت ، والذي يعدل الخصائص والأساليب في الفصل.
يمكن أن يؤدي استخدام الكلمة الرئيسية الثابتة إلى تلبية متطلبات اثنين:
(1) أحد الموقف هو أنك تريد فقط استخدام منطقة تخزين لحفظ بيانات معينة - بغض النظر عن عدد الكائنات التي تريد إنشاؤها ، حتى أنك لا تنشئ كائنات على الإطلاق ؛ تسمى السمات التي تم تعديلها بواسطة ثابت الخصائص الثابتة ، وأحد أهم الميزات الأساسية لهذا النوع من السمات هي أنها سمات فئة ، وليس كائنات محددة لأي فئة. بمعنى آخر ، بالنسبة لأي كائن محدد من هذه الفئة ، فإن الخاصية الثابتة هي وحدة تخزين شائعة. عندما يصل أي كائن من أي فئة إلى ذلك ، فإنه يحصل على نفس القيمة العددية. عندما يقوم أي كائن في أي فئة بتعديله ، فإنه يقوم أيضًا بعمليات على نفس وحدة الذاكرة.
(2) موقف آخر هو أننا نحتاج إلى طريقة خاصة غير مرتبطة بأي كائن من هذه الفئة. وهذا يعني ، حتى لو لم يتم إنشاء الكائن ، هناك حاجة إلى طريقة يمكن استدعاؤها مباشرة من قبل الفصل.
غرض مهم من الثابت هو مساعدتنا على استدعاء هذه الطريقة دون الحاجة إلى إنشاء كائن.
الثوابت الثابتة
المتغيرات الثابتة نادرة. ومع ذلك ، الثوابت الثابتة شائعة. على سبيل المثال ، يتم تعريف ثابت ثابت في فئة الرياضيات:
الرياضيات الطبقة العامة
{... Public Static Final Double Pi = 3.1.4159265358979323846 ؛ ...} تعلن الطريقة الثابتة أن الطريقة ثابتة لها ثلاثة معاني على الأقل:
(1) عند استخدام هذه الطريقة ، يجب استخدام اسم الفئة كبادئة ، بدلاً من اسم كائن معين ؛
(2) الأساليب غير القتالية هي الأساليب التي تنتمي إلى كائن. عند إنشاء هذا الكائن ، تحتوي طريقة الكائن على شريحة رمز مخصصة في الذاكرة ؛ على الرغم من أن الطريقة الثابتة تنتمي إلى الفئة بأكملها ، وسيتم تخصيص شريحة الكود في الذاكرة وتحميلها وفقًا لتعريف الفئة ولن تكون حصرية لأي كائن ؛
(3) نظرًا لأن الطريقة الثابتة تنتمي إلى الفئة بأكملها ، فإنها لا تستطيع معالجة متغيرات الأعضاء ومعالجتها التي تنتمي إلى كائن معين ، ولكن يمكنها فقط معالجة متغيرات الأعضاء التي تنتمي إلى الفئة بأكملها.
5 الطريقة الرئيسية
لا تنطبق الطريقة الرئيسية العمليات على أي كائن. في الواقع ، عندما يبدأ البرنامج في التنفيذ ، لا توجد كائنات حتى الآن. يتم تنفيذ الطريقة الثابتة ويتم إنشاء الكائنات المطلوبة من قبل البرنامج.
يطالب أن كل فئة يمكن أن يكون لها طريقة رئيسية. هذه خدعة مريحة للغاية لفصول اختبار الوحدة.
الخلاصة عبارة عن تعديل مجردة يمكن استخدامها لتعديل الفئات أو الأساليب.
فئة مجردة
عندما يتم الإعلان عن الفصل مجردة ، يطلق على هذا الفصل فئة مجردة. ما يسمى الفئة التجريدية هي فئة بدون كائنات مثيل ملموسة.
لمعالجة هذه المشكلة ، توفر Java آلية تسمى "الطريقة التجريدية". إنه ينتمي إلى طريقة غير مكتملة ، مع إعلان واحد فقط ، وليس له أي طريقة. فيما يلي بناء الجملة المستخدمة عند إعلان الطرق التجريدية:
مجردة void x () ؛
طرق مجردة
كمعدل طريقة الفصل ، يعلن الملخص طريقة تجريدية لها رؤوس طريقة فقط ولكن لا يوجد طريقة محددة لتنفيذ هيئة وتنفيذ التشغيل.
يمكن ملاحظة أن الطريقة المجردة تحتوي فقط على إعلان رأس الطريقة ، ويتم استخدام فاصلة فاصلة لاستبدال تعريف هيكل الطريقة: أما بالنسبة للتنفيذ المحدد لجسم الطريقة ، فقد تم إكماله بواسطة فئات فرعية مختلفة من الفئة الحالية في تعريفات الفئة الخاصة بها.
تجدر الإشارة إلى أن جميع الأساليب المجردة يجب أن تكون موجودة في فصول مجردة
وسط.
بالإضافة إلى الطرق المجردة ، يمكن أن تحتوي الفئات المجردة أيضًا على بيانات وطرق ملموسة.
الأساليب المجردة هي مفاهيم مهمة للغاية في لغة برمجة Java. سوف تستخدمه بعدة طرق في الواجهة.
ملاحظة: هنا نحتاج إلى مقارنة وحفظ الواجهة. الأساليب في الواجهة كلها طرق مجردة. بالطبع ، هناك أيضًا سمات في الواجهة ، وسيتم وصف خصائصها المحددة بالتفصيل لاحقًا.
الفصل النهائي ، السمة النهائية ، الطريقة النهائية و Finalizer (لا يوجد معدل نهائي في C ++)
النهائي هو المعدل النهائي ، الذي يعدل الفئات والخصائص والأساليب. بالإضافة إلى ذلك ، فإن الكلمات الرئيسية للمحطة تشبه إلى حد كبير النهائي ، وسيتم تقديمها معًا
الفصل النهائي
إذا تم الإعلان عن الفصل النهائي ، فهذا يعني أنه لا يمكن استخلاص فئات فرعية جديدة ولا يمكن أن يتم مورثها كفئة الوالدين. لذلك ، لا يمكن الإعلان عن فئة مجردة ونهائية.
عادة ما تكون الفئات المعرفة بأنها نهائية بعض الفئات ذات الوظائف الخاصة المستخدمة لإكمال الوظائف القياسية. يمكن أن يحدد تحديد الفئة كنهائيات محتواها وسماتها ووظائفها وتشكيل علاقة رسم خرائط مستقرة مع اسم الفصل ، مما يضمن أن تكون الوظائف التي يتم تنفيذها عند الإشارة إلى هذه الفئة دقيقة.
السمات النهائية
لدى العديد من لغات البرمجة طرقها الخاصة لإخبار المترجم بأن بيانات معينة هي "ثابت". تستخدم الثوابت بشكل أساسي في الجانبين التاليين:
(1) فترة التجميع ثابت ، لن تتغير أبدًا ؛
(2) لا نريد تغيير قيمة أثناء وقت التشغيل.
يمكن تعريف حقل مثيل على أنه نهائي (لا يمكن تغييره). يجب تهيئة هذا الحقل عند بناء الكائن. أي أنه يجب ضمان ضبط القيمة قبل نهاية كل مُنشئ. لا يمكن تغيير قيمة الحقل في المستقبل
الطريقة النهائية
قد يكون سبب استخدام الطريقة النهائية بسبب اعتبارات لسببين.
الأول هو "قفل" طريقة منع أي فئة الميراث من تغيير معناها الأصلي. عند تصميم برنامج ما ، يمكن أخذ هذه الممارسة إذا كنت تريد أن تظل سلوك الطريقة دون تغيير أثناء الميراث ولا يمكن الكتابة أو إعادة كتابتها.
السبب الثاني لتبني الطريقة النهائية هو كفاءة تنفيذ البرنامج
المنهي
وظيفة Terminator هي طريقة تنفذ عند استرداد الكائنات. على غرار الطريقة التي يتم بها تنفيذ المنشآت عند إنشاء كائنات.
مثال
voidfinalize () {system.out.println ("") ؛ }المعدلات الأخرى
متقلب
إذا تم تعديل السمة بواسطة متقلبة ، فهذا يعني أنه يمكن التحكم في هذه السمة وتعديلها بواسطة عدة مؤشرات ترابط في نفس الوقت.
متزامن
يستخدم بشكل أساسي لمزامنة الخيط
محلي
وهذا يعني أن الطريقة غير مكتوبة بلغة Java (مكتوبة في C و C ++ ولغات أخرى)
بعض المعلومات الموجودة على الإنترنت: - الفئة الداخلية
ببساطة ، الفصول الداخلية هي فصول في الفصول ، على سبيل المثال:
الفئة A {private int i ؛ private void m () {} class b {mm (int j) {i = j ؛ m () ؛}}}هنا ، B هي الفئة الداخلية لـ A ، والتي تتميز بالوصول المريح إلى الأساليب والخصائص الخاصة في الطبقات الخارجية. على سبيل المثال ، يمكن هنا الوصول مباشرة إلى الخصائص الخاصة I والطرق الخاصة M () في A.
أهم ميزات البرمجة الموجهة للكائنات هي التغليف (وتسمى أيضًا التجريد) ، والميراث وتعدد الأشكال. كلغة برمجة موجهة نحو الكائن ، Java لديها مزاياها الخاصة في هذا الصدد:
"الميراث هو شكل من أشكال إعادة استخدام البرمجيات ، وهو فعال في تقليل تعقيد البرامج. يعد الميراث أيضًا ميزة لغة البرمجة الموجهة للكائنات. اللغات التي تتبنى كائنات ولكن ليس لها ميراث هي لغات قائمة على الكائنات ، ولكنها ليست اللغات الموجهة للكائنات. هذا هو الفرق بين الاثنين."
علاقة الميراث بين الطبقات هي محاكاة مباشرة للعلاقات الوراثية في العالم الحقيقي. ويمثل العلاقة الجوهرية بين الفئات ومشاركة السمات والعمليات ، أي أن الفئات الفرعية يمكن أن تتبع ميزات معينة من الفئة الأصل (الفئة الموروثة). بالطبع ، يمكن أن يكون للفئات الفرعية خصائص وعمليات مستقلة خاصة بها
الميراث هو شكل من أشكال إعادة استخدام البرمجيات. يتم إنشاء فصول جديدة بواسطة الفئات الحالية ، ويتم إضافة سمات وسلوكيات جديدة عن طريق الاحتفاظ بخصائصها وسلوكياتها ، وتعديل الأداء وفقًا لمتطلبات الفئة الجديدة. إذا كانت فئة الطفل ترث فقط من فئة الوالدين ، فسيطلق عليها ميراثًا واحدًا ؛ إذا كانت فئة الطفل ترث من أكثر من فئة من الوالدين ، فإنه يطلق عليه متعددة. لاحظ أن Java لا يدعم الميراث المتعدد ، ولكنه يدعم مفهوم "الواجهة". تسمح واجهات Java بالحصول على العديد من مزايا الميراث المتعدد والتخلي عن العيوب المقابلة. ملاحظة: C ++ يدعم الميراث المتعدد
تعريف علاقة الميراث:
[Modifier] اسم الفئة الفرعية يمتد اسم الفئة الأصل ، اسم الفئة الوالدين 2
يتبع اسم فئة الوالدين
يتم استخدام الكلمة الرئيسية للإشارة إلى الفئة الفرعية للفئة الحالية موجودة بالفعل ، وهناك علاقة ميراث.
تحديد فئتين فرعيتين من موظف فئة الموظفين:
فئة الموظف العام: موظف مشترك
فئة المشرف: مدير الموظفين
هناك جانبان رئيسيان لميراث الفئة الفرعية من فئة الوالدين:
(1) ميراث السمات. على سبيل المثال ، الشركة هي فئة أولياء الأمور ، ولديها اسم ، عنوان ، مدير ، موظف ، وما إلى ذلك ، وكلها جوانب هيكلية.
(2) الميراث طريقة. تحدد فئة الوالدين العديد من العمليات ، مثل الشركة التي تحتاج إلى مشاريع وأرباح وتعيين المديرين وتجنيد الموظفين ، وما إلى ذلك ، وسترث الشركة الفرعية هذه الإجراءات ؛
classCommOnemployeExtends موظف // الفئة الفرعية 1: {intm_managerno ؛ // تحديد سمة الفئة m_managerno ، التي تمثل رقم رئيس الموظف} classManagerEmployeExtends الموظف // الفئة الفرعية 2: {intm_secretaryno ؛ تنسب الميراث والاختباء
على الرغم من أن فئة الموظف هي فئة من الوالدين ، إلا أنها لا تعني أنها تحتوي على المزيد من الوظائف لمجرد أنها فئة من الوالدين. على العكس من ذلك ، فإن الأدوات الفرعية لها وظائف أكثر من فئات الوالدين. نظرًا لأن الفئة الفرعية عبارة عن امتداد للفئة الأصل ، فإن السمات والأساليب التي لم تتم إضافتها (1) لا يمكن للفئة الفرعية الوصول إلى العضو الخاص في فئة الأصل ، ولكن يمكن للفئة الفرعية الوصول إلى الجمهور من فئة الأم.
(2) الوصول المحمي هو مستوى وسيط وقائي بين الوصول العام والخاص.
(3) نظرًا لأن أعضاء فئة الوالدين الموروثة لم يتم سردهم في إعلان الفئة الفرعية ، فإن هؤلاء الأعضاء موجودون في الفئة الفرعية.
هنا ، نحتاج إلى التمييز بين الميراث ، والكتابة فوق الحمل ، والعديد من المفاهيم المربكة:
فقط على المستوى المفاهيمي للطريقة ، يمكن الخلط بين هذه المفاهيم الثلاثة بسهولة:
طريقة الميراث
بالنسبة للكائنات الفرعية ، يمكن استخدام طرق من الفئة الأصل. حتى إذا لم يتم تعريف هذه الطرق بوضوح في الفئة الفرعية ، فإنها ورثت تلقائيًا من الفئة الأصل.
تغطية الطريقة
تشير Method Override إلى: طريقة تحدد طريقة تحمل نفس الاسم للكتابة فوق فئة الأصل ، وهي تنفيذ تقنية الأشكال. عندما تتم كتابة طريقة فئة الأصل في فئة الطفل ، عادة ما يكون إصدار فئة الطفل هو الذي يدعو إلى إصدار الفئة الأصل ويقوم ببعض الأعمال الإضافية.
هناك أشياء كثيرة يجب ملاحظتها. هنا ، أذكر هذا أساسا هذا وسوبر. هناك هذا في C ++ (والمفهوم مشابه للمفهوم في Java) ، ولكن لا يوجد سوبر.
هذا يمثل الكائن الحالي نفسه ، وهذا يمثل إشارة إلى الكائن الحالي. يمكن فهمه كاسم آخر للكائن. يتيح لك ذلك استدعاء أساليب وخصائص الكائن الحالي.
على سبيل المثال: this.getName () و getName () هي نفسها في الفصل.
يمثل Super كائن الفئة Parent Direct للكائن الحالي ، وهو طريقة مرجعية زائدة من كائن الفئة الأصل للكائن الحالي.
تعريف الحمل الزائد: يمكن تعريف الطريقة بنفس اسم الطريقة ولكن جداول المعلمة المختلفة (الرقم أو النوع أو ترتيب المعلمات في جدول المعلمة له قيم مختلفة) ، والتي تسمى الأسلوب الزائد.
• التحميل الزائد: يحدث التحميل الزائد عندما يكون للطرق المتعددة نفس الاسم وتحتوي على معلمات مختلفة. يجب على المترجم اختيار الطريقة التي يمكن الاتصال بها. إنه يختار الطريقة الصحيحة من خلال مقارنة أنواع المعلمات في رؤوس طريقة مختلفة مع أنواع القيم المستخدمة في مكالمات طريقة محددة.
يسمح تعدد الأشكال بمعالجة المتغيرات الموجودة والفئات ذات الصلة بأسلوب موحد ، مما يجعل من السهل إضافة ميزات جديدة في النظام. هنا ، يمكن نشر المعلومات التي عثرت عليها عبر الإنترنت أن يوضح بشكل أوضح الأشكال المتعددة وقضايا الميراث التي تحتاج إلى اهتمام خاص في الميراث:
تعدد الأشكال من جافا
تحتوي البرمجة الموجهة نحو الكائنات على ثلاث خصائص ، وهي التغليف والميراث وتعدد الأشكال.
يخفي التغليف آلية التنفيذ الداخلية للفئة ، بحيث يمكن تغيير البنية الداخلية للفئة دون التأثير على المستخدم ، مع حماية البيانات.
الوراثة هي إعادة استخدام رمز فئة الأصل أثناء التحضير لتنفيذ تعدد الأشكال. إذن ما هو تعدد الأشكال؟
طريقة إعادة الكتابة والتحميل الزائد والاتصال الديناميكي تشكل تعدد الأشكال. أحد الأسباب التي تجعل جافا قد قدمت مفهوم تعدد الأشكال هو أنه يختلف عن C ++ من حيث الميراث الطبقي. هذا الأخير يسمح بميراث متعدد ، والذي يجلبها وظائف قوية للغاية ، لكن علاقة الميراث المعقدة تجلب أيضًا مشكلة أكبر لمطوري C ++. من أجل تجنب المخاطر ، لا تسمح Java إلا بالميراث الفردي ، وهناك علاقة IS-A بين الطبقات المشتقة والفئات الأساسية (أي "القطط" هي "حيوان"). على الرغم من أن القيام بذلك يضمن بساطة ووضوح علاقة الميراث ، إلا أنه سيكون له حتمية قيود وظيفية كبيرة. لذلك ، قدمت Java مفهوم تعدد الأشكال للتعويض عن هذا القصور. بالإضافة إلى ذلك ، تعد الطبقات والواجهات المجردة أيضًا وسيلة مهمة لحل حدود لوائح الميراث الفردي. في الوقت نفسه ، يعتبر تعدد الأشكال أيضًا جوهر البرمجة الموجهة للكائن.
لفهم تعدد الأشكال ، يجب أولاً معرفة ماهية "التحول التصاعدي".
لقد حددت قطة فئة فرعية ، والتي ترث فئة الحيوانات ، والأخير هو أن الأول هو الطبقة الوالدية. يمكنني المرور
Cat C = New Cat () ؛
ليس من الصعب فهم إنشاء كائن قط. لكن عندما أعرّفها مثل هذا:
Animal A = New Cat () ؛
ماذا يعني هذا؟
الأمر بسيط ، فهذا يعني أنني أحدد إشارة نوع الحيوان إلى كائن تم إنشاؤه حديثًا من نوع القط. نظرًا لأن CAT ورثت من Animal Plant Class ، فإن الإشارة إلى نوع الحيوان يمكن أن تشير إلى كائن من نوع القط. إذن ما الهدف من القيام بذلك؟ نظرًا لأن الفئات الفرعية هي تحسن وتمديد للفئة الأصل ، فإن الفئات الفرعية أكثر قوة بشكل عام من فئات الوالدين في الوظيفة ، وسماتها أكثر فريدة من فئات الوالدين.
إن تحديد إشارة إلى نوع فئة الوالدين يشير إلى كائن يتم فئاته الفرعية لا يمكن فقط استخدام الوظائف القوية للفئة الفرعية ، ولكن أيضًا استخراج القواسم المشتركة للفئة الأم.
لذلك ، يمكن للإشارة إلى نوع الفئة الأصل استدعاء جميع الخصائص والأساليب المحددة في الفئة الأصل ، وهي عاجزة للطرق المحددة في فئة الطفل ولكن ليس في فئة الوالدين ؛
في الوقت نفسه ، لا يمكن استدعاء طريقة في الفئة الأصل إلا من خلال إشارة إلى نوع الفئة الأصل إذا تم تعريفها في الفئة الأصل ولكن لم يتم تجاوزها في فئة الطفل ؛
بالنسبة للطرق المحددة في الفئة الأصل ، إذا تم إعادة كتابة الطريقة في فئة الطفل ، فإن الإشارة إلى نوع الفئة الأصل سوف تستدعي هذه الطريقة في فئة الطفل ، وهو اتصال ديناميكي.
انظر إلى البرنامج التالي:
فئة الأب {public void func1 () {func2 () ؛ } // هذه هي طريقة func2 () في الفئة الأصل ، لأن الطريقة يتم تجاوزها في الفئة الفرعية أدناه // لذلك عند استدعاءها في مرجع نوع الفئة الأصل ، لن تكون هذه الطريقة صالحة // استبدال طريقة func2 () في الفئة الفرعية الفئة الفرعية func2 () }} Class Child يمتد الأب {// func1 (int i) هو حمولة زائدة من طريقة func1 () // لأن هذه الطريقة غير محددة في الفئة الأصل ، لا يمكن استدعاؤها من خلال مرجع نوع الفئة الأصل // لذلك في الطريقة الرئيسية أدناه Child.Func1 (68) خاطئ punc1 (int i) {system.out.println }. }} تعدد الأشكال الفئة العامة {public static void main (string [] args) {الأب تشايلد = طفل جديد () ؛ child.func1 () ؛ // ماذا ستكون نتيجة الطباعة؟ }}البرنامج أعلاه هو مثال نموذجي للغاية على تعدد الأشكال. يرث الطفل من فئة الطفل الأب من فئة الوالدين ، ويزيد من طريقة فئة الوالدين FUNC1 () ، ويكتب طريقة فئة الوالدين FUNC2 (). لم يعد FUNC1 (int i) و func1 () نفس الطريقة. نظرًا لعدم وجود func1 (int i) في الفصل الأصل ، لا يمكن للطفل المرجعي لنوع الفئة الأصل استدعاء طريقة func1 (int i). إذا تجاوزت الفئة الفرعية طريقة FUNC2 () ، فسيقوم الطفل المرجعي لنوع الفئة الأصل بالاتصال بـ FUNC2 () المعاد كتابته في الفئة الفرعية عند استدعاء الطريقة.
إذن ما هي النتائج التي سيطبعها البرنامج؟
من الواضح ، يجب أن يكون "CCC".
من أجل تعدد الأشكال ، يمكن تلخيصه على النحو التالي:
(1) استخدام مراجع نوع الفئة الأصل للإشارة إلى كائن الفئة الفرعية (الكائن الفعلي) ؛
(2) يمكن لهذا المرجع فقط استدعاء طرق والمتغيرات المحددة في الفئة الأصل ؛
(3) إذا تم إعادة كتابة طريقة في الفئة الأصل في الفئة الفرعية ، ثم عند استدعاء هذه الطريقة ، سيتم استدعاء الطريقة في الفئة الفرعية ؛ (اتصال ديناميكي ، مكالمة ديناميكية)
(4) لا يمكن إعادة كتابة المتغيرات (تجاوز). مفهوم "إعادة الكتابة" هو فقط للطرق. إذا كانت "إعادة كتابة" المتغيرات في الفئة الأصل في الفئة الفرعية ، فسيتم الإبلاغ عن خطأ أثناء التجميع.
تعدد الأشكال من خلال:
(1) الواجهة وتنفيذ الواجهة والكتابة فوق العديد من الفئات المختلفة التي تغطي نفس الطريقة في الواجهة (2) الفئة الأصل والفئة الأم والفئة الأم والكتابة عدة فئات فرعية مختلفة تغطي نفس الطريقة في الفئة الأصل.
1. المفاهيم الأساسية
تعدد الأشكال: أرسل رسالة إلى كائن ودع الكائن يقرر السلوك الذي يجب الرد عليه.
يتم تنفيذ مكالمات الطريقة الديناميكية عن طريق تعيين مراجع كائن الفئة الفرعية إلى متغيرات مرجع كائن الفئة الفائقة.
تتبع آلية AVA هذه مبدأ: عندما يشير كائن فائق الفئة إلى متغير للإشارة إلى كائن فئة فرعية ، فإن نوع الكائن المشار إليه بدلاً من نوع المتغير المشار إليه ، يحدد طريقة العضو التي يتم استدعاؤها ، ولكن يجب تحديد الطريقة المسمى في الفئة الفائقة ، أي الطريقة التي يغطيها الفرسان الفرعي.
(1) إذا كان A مرجعًا إلى الفئة A ، فيمكن أن يشير A إلى مثيل من الفئة A ، أو إلى فئة فرعية من الفئة A.
(2) إذا كان A مرجعًا إلى الواجهة A ، فيجب أن يشير A إلى مثيل لفئة تنفذ الواجهة A.
آلية تنفيذ تعدد الأشكال جافا
آلية تنفيذ JVM الحالية من Sun ، مرجع مثيل الفصل هو مؤشر للمقبض ، وهو زوج من المؤشرات:
يشير المؤشر إلى طاولة ، وفي الواقع ، يحتوي هذا الجدول أيضًا على مؤشرين (يشير أحد المؤشرات إلى جدول طريقة يحتوي على الكائن ، والمؤشر الآخر إلى كائن فئة ، يشير إلى النوع الذي ينتمي إليه الكائن) ؛
يشير مؤشر آخر إلى قطعة من مساحة الذاكرة المخصصة من كومة Java.
لخص
(1) يتم تنفيذ مكالمات الطريقة الديناميكية عن طريق تعيين مراجع كائن الفئة الفرعية إلى متغيرات مرجع كائن الفئة الفائقة.
derivedc c2 = new derivedc () ؛ BaseClass A1 = C2 ؛ // فئة قاعدة BaseClass ، DerivedC هي a1.play () الموروثة من baseclass ؛ //play() is defined in BaseClass and DerivedC, that is, the subclass overrides the method
分析:
* 为什么子类的类型的对象实例可以覆给超类引用?
自动实现向上转型。通过该语句,编译器自动将子类实例向上移动,成为通用类型BaseClass;
* a.play()将执行子类还是父类定义的方法?
子类的。在运行时期,将根据a这个对象引用实际的类型来获取对应的方法。所以才有多态性。一个基类的对象引用,被赋予不同的子类对象引用,执行该方法时,将表现出不同的行为。
在a1=c2的时候,仍然是存在两个句柄,a1和c2,但是a1和c2拥有同一块数据内存块和不同的函数表。
(2)不能把父类对象引用赋给子类对象引用变量
BaseClass a2=new BaseClass(); DerivedC c1=a2;//出错
在java里面,向上转型是自动进行的,但是向下转型却不是,需要我们自己定义强制进行。
c1=(DerivedC)a2; 进行强制转化,也就是向下转型.
(3)记住一个很简单又很复杂的规则,一个类型引用只能引用引用类型自身含有的方法和变量。
你可能说这个规则不对的,因为父类引用指向子类对象的时候,最后执行的是子类的方法的。
其实这并不矛盾,那是因为采用了后期绑定,动态运行的时候又根据型别去调用了子类的方法。而假若子类的这个方法在父类中并没有定义,则会出错。
例如,DerivedC类在继承BaseClass中定义的函数外,还增加了几个函数(例如myFun())
分析:
当你使用父类引用指向子类的时候,其实jvm已经使用了编译器产生的类型信息调整转换了。
这里你可以这样理解,相当于把不是父类中含有的函数从虚拟函数表中设置为不可见的。注意有可能虚拟函数表中有些函数地址由于在子类中已经被改写了,所以对象虚拟函数表中虚拟函数项目地址已经被设置为子类中完成的方法体的地址了。
(4)Java与C++多态性的比较
jvm关于多态性支持解决方法是和c++中几乎一样的,
只是c++中编译器很多是把类型信息和虚拟函数信息都放在一个虚拟函数表中,但是利用某种技术来区别。
Java把类型信息和函数信息分开放。Java中在继承以后,子类会重新设置自己的虚拟函数表,这个虚拟函数表中的项目有由两部分组成。从父类继承的虚拟函数和子类自己的虚拟函数。
虚拟函数调用是经过虚拟函数表间接调用的,所以才得以实现多态的。
Java的所有函数,除了被声明为final的,都是用后期绑定。
1个行为,不同的对象,他们具体体现出来的方式不一样,
比如: 方法重载overloading 以及方法重写(覆盖)override
class Human{ void run(){输出人在跑} } class Man extends Human{ void run(){输出男人在跑} } 这个时候,同是跑,不同的对象,不一样(这个是方法覆盖的例子) class Test{ void out(String str){输出str} void out(int i){输出i} }这个例子是方法重载,方法名相同,参数表不同
ok,明白了这些还不够,还用人在跑举例
Human ahuman=new Man();
这样我等于实例化了一个Man的对象,并声明了一个Human的引用,让它去指向Man这个对象意思是说,把Man这个对象当Human看了.
比如去动物园,你看见了一个动物,不知道它是什么, "这是什么动物? " "这是大熊猫! "
这2句话,就是最好的证明,因为不知道它是大熊猫,但知道它的父类是动物,所以,
这个大熊猫对象,你把它当成其父类动物看,这样子合情合理.
这种方式下要注意new Man();的确实例化了Man对象,所以ahuman.run()这个方法输出的是"男人在跑"
如果在子类Man下你写了一些它独有的方法比如eat(),而Human没有这个方法,
在调用eat方法时,一定要注意强制类型转换((Man)ahuman).eat(),这样才可以...
对接口来说,情况是类似的...
مثال:
package domain; //Define superA class superA { int i = 100; void fun(int j) { j = i; System.out.println("This is superA"); } } //Define superA subclass subB class subB extends superA { int m = 1; void fun(int aa) { System.out.println("This is subB"); } } //Define superA subC class subC extends superA { int n = 1; void fun(int cc) { System.out.println("This is subB"); } } //Define superA subC class subC extends superA { int n = 1; void fun(int cc) { System.out.println("This is subC"); } } class Test { public static void main(String[] args) { superA a = new superA(); subB b = new subB(); subC c = new subC(); أ = ب ؛ a.fun(100); أ = ج ؛ a.fun(200); }} /*
* 上述代码中subB和subC是超类superA的子类,我们在类Test中声明了3个引用变量a, b,
* c,通过将子类对象引用赋值给超类对象引用变量来实现动态方法调用。也许有人会问:
* "为什么(1)和(2)不输出:This is superA"。
* java的这种机制遵循一个原则:当超类对象引用变量引用子类对象时,
* 被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,
* 但是这个被调用的方法必须是在超类中定义过的,
* 也就是说被子类覆盖的方法。
* 所以,不要被上例中(1)和(2)所迷惑,虽然写成a.fun(),但是由于(1)中的a被b赋值,
* 指向了子类subB的一个实例,因而(1)所调用的fun()实际上是子类subB的成员方法fun(),
* 它覆盖了超类superA的成员方法fun();同样(2)调用的是子类subC的成员方法fun()。
* 另外,如果子类继承的超类是一个抽象类,虽然抽象类不能通过new操作符实例化,
* 但是可以创建抽象类的对象引用指向子类对象,以实现运行时多态性。具体的实现方法同上例。
* 不过,抽象类的子类必须覆盖实现超类中的所有的抽象方法,
* 否则子类必须被abstract修饰符修饰,当然也就不能被实例化了
*/
以上大多数是以子类覆盖父类的方法实现多态.下面是另一种实现多态的方法-----------重写父类方法
JAVA里没有多继承,一个类之能有一个父类。而继承的表现就是多态。一个父类可以有多个子类,而在子类里可以重写父类的方法(例如方法print()),这样每个子类里重写的代码不一样,自然表现形式就不一样。这样用父类的变量去引用不同的子类,在调用这个相同的方法print()的时候得到的结果和表现形式就不一样了,这就是多态,相同的消息(也就是调用相同的方法)会有不同的结果。举例说明:
//Premary class public class Father{ //The parent class has a method to hit the child public void hitChild(){ } } //Subclass 1 public class Son1 extends Father{ //Rewrite the method to hit the child public void hitChild(){ System.out.println("Why hit me? What I did wrong!"); } } //Subclass 2 public class Son2 extends Father{ //Rewrite the method to hit the child public void hitChild(){ System.out.println("I know I'm wrong, stop hitting it!"); } } //Subclass 3 public class Son3 extends Father{ //Rewrite the parent class hits the child method public void hitChild(){ System.out.println("I run, you can't hit!"); } } //Test class public class Test{ public static void main(String args[]){ Father father; father = new Son1(); father.hitChild(); father = new Son2(); father.hitChild(); father = new Son3(); father.hitChild(); }}都调用了相同的方法,出现了不同的结果!这就是多态的表现!
import java.io.*;class Super{ Super(){ System.out.println("This is super class!"); } void method(){ System.out.println("Super's method"); }}class Sub extends Super{ Sub(){ super(); System.out.println("/n/t:and here is the child"); } void method(){ System.out.println("child's method"); }}public class Super_Sub{ public static void main(String[] args){ Super sup=new Sub(); sup.method(); Sub child=(Sub)new Super();//这里,实际分配的内存是Super的,但是却用Child来指代它,这就是“向下转型”(父类冒充子类,因为子类在UML中画时是在下的嘛),必经强制类型转换child.method(); }}对于数据来说,继承是否为正确的设计可以用一个简单的规则来判断。“is-a”规则表明子类的每一个对象都是一个超类的对象。例如,每一个经理是一个员工。然而,只有经理类是员工类的子类才是有意义的。很明显,反过来就不行了――并不是每个员工都是经理。
还有一个明确叙述“is-a”规则的方法是替代原则。该原则规定无论何时,如果程序需要一个超类对象,都可以用一个子类对象来代替
动态绑定
理解调用一个对象方法的机制是非常重要的。下面具体介绍:Xf;
(1)编译器检查对象的声明类型和方法名。
(2)接着,编译器检查方法调用中的参数类型。如果在所有的叫做f的方法中有一个其参数类型同调用提供的参数类型最匹配,那么该方法就会被选择调用。这个过程称作超载选择。(静态)
(3)当程序运行并且使用动态绑定来调用一个方法时,那么虚拟机必须调用同x所指向的对象的实际类型相匹配的方法版本。
...
如果类中没有写构造函数,那么系统会自动为该类提供一个默认构造函数,该构造函数将所有的实例字段初始化为默认值:
...
包用途:
Java允许把多个类收集在一起成为一组,称作包(package)。包便于组织任务,以及使自己的任务和其他人提供的代码库相分离。
标准Java库被分类成许多的包,其中包括java.1ang、java.util和java.net等等。标准Java包是分层次的。就像在硬盘上嵌套有各级子目录一样,可以通过层次嵌套组织包。所有的Java包都在Java和Javax包层次内
创建包
已经看到,已有的库,比如JavaAPI中的类和接口,可以导入到Java程序中。
Java API中的每一个类和接口属于一个特定的包。它包含一组相关联的类和接口,实际是对类和接口进行组织的目录结构。
例如,假定文件名是MyClass.java。它意味着在那个文件有一个、而且只能有一个public类。而且那个类的名字必须是MyClass(包括大小写形式):
packagemypackage;publicclass MyClass{……}创建可复用的类的步骤简要说明如下:
(1)定义一个public类。如果类不是public,它只能被同一包中的其他类使用。
(2)选择一个包名,并把package语句加到可复用的类的源代码文件中。
(3)编译这个类。这样,它就被放到适当的包目录结构中,以供编译器和解译器使用。
(4)把这个可复用的类导入到需要用它的程序中。现在就可以使用它了。
注意在Java语言中可以出现在类定义的括号外面的仅有两个语句,它们是package和import。
包引用---每个类名前加上完整的包名
例如,给出一个指向此包中的类的快捷方式。一旦使用import(导入)了以后,就不再需要给出完整的包名。
可以引入一个特定的类,也可以引入整个包。import语句要放在源文件的头部(但在所有package语句的下面)。例如,可以通过下面的语句引入在java.util包中的所有的类:
importjava.util.*;
然后,就可以使用
Datetoday=new Date();
而不需要在前面加上包名。也可以引入包中某个特定的类:
importjava.util.Date;
要把类放人一个包中,必须把此包的名字放在源文件头部,并且放在对包中的类进行定义的代码之前。例如,在文件Employee.java的开始部分如下:
packagecom.horstmann.corejava;publicclass Employee{……}把包中的文件放入与此完整的包名相匹配的子目录中。例如,在包com.horstmann.corejava中的所有的类文件都必须放在子目录com/horstmann/core.java(Windows下的com/horstmann/corejava)下。这是最简单的一种方法
类被存储在文件系统的子目录中。类的路径必须与所在包名相匹配。
在前面的例子中,包目录com/horstmann/corejava是程序目录的一个子目录。然而这样安排很不灵活。一般,有多个程序需要访问包文件。为了使包可以在多个程序间共享,需要做以下事情:
1)把类放在一个或多个特定的目录中,比如/home/user/classdir。此目录是包树的基本目录。如果加入了类com.horstmann.corejava.Employee,那么此类文件必须位于子目录/home/user/classdir/com/horstmann/corejava下。
2)设置类路径。类路径是其子目录包含类文件的所有基本目录的集合。classpath
已经接触过public和private访问指示符。
被标记为Public的部件可以被任何类使用,而私有部件只能被定义它们的类使用。如果没有指定public或private,那么部件(即类、方法或变量)可以被同一个包中的所有方法访问。
Java API包
为了简化面向对象的编程过程,Java系统事先设计并实现了一些体现了常用功能的标准类,如用于输入/输出的类,用于数学运算的类,用于图形用户界面设计的类,用于网络处理的类等。这些系统标准类根据实现的功能不同,可以划分成不同的集合,每个集合是一个包,合称为类库。可以引用这些包,也可以创建自己的包。
Java的类库是系统提供的已实现的标准类的集合,是Java编程的API,它可以帮助开发者方便、快捷地开发Java程序
接口主要作用是可以帮助实现类似于类的多重继承的功能。在Java中,出于简化程序结构的考虑,不再支持类间的多重继承而只支持单重继承,即一个类至多只能有一个直接父类。然而在解决实际问题的过程中,仅仅依靠单重继承在很多情况下都不能将问题的复杂性表述完整,需要其他的机制作为辅助。
接口声明
Java中声明接口的语法如下:
[public] interface 接口名[extends 父接口名列表]{ //接口体;//常量域声明[public] [static] [final] 域类型域名=常量值; //抽象方法声明[public] [abstract] 返回值方法名(参数列表) [throw异常列表];}从上面的语法规定可以看出,定义接口与定义类非常相似,实际上完全可以把接口理解成为一种特殊的类,接口是由常量和抽象方法组成的特殊类
(1)接口中的属性都是用final修饰的常量,
(2)接口中的方法都是用abstract修饰的抽象方法,在接口中只能给出这些抽象方法的方法名、返回值和参数列表,而不能定义方法体,即仅仅规定了一组信息交换、传输和处理的“接口”
接口的实现
一个类要实现某个或某几个接口时,有如下的步骤和注意事项:
(1)在类的声明部分,用implements关键字声明该类将要实现哪些接口;
如下:
class类名implements接口{ }(2)如果实现某接口的类不是abstract的抽象类,则在类的定义部分必须实现指定接口的所有抽象方法,即为所有抽象方法定义方法体,而且方法头部分应该与接口中的定义完全一致,即有完全相同的返回值和参数列表;
(3)如果实现某接口的类是abstract的抽象类,则它可以不实现该接口所有的方法。
(4)一个类在实现某接口的抽象方法时,必须使用完全相同的方法头。
(5)接口的抽象方法,其访问限制符都已指定是public,所以类在实现方法时,必须显式地使用public修饰符。
ملخص:
多重继承是指一个子类继承多个父类。Java不支持多重继承,但Java提供了接口。
子类不能访问父类的private成员,但子类可以访问其父类的public,protected和包访问成员;要访问父类的包访问成员,子类一定要在父类的包内。
子类构造函数总是先调用(显式的或隐式地)其父类的构造函数,以创建和初始化子类的父类成员。
子类的对象可以当作其父类的对象对待,反之则不行(即向上转型)
protected访问是public和private访问之间一个保护性的中间层次。父类方法、子类方法和在同一个包内类的方法都能访问父类的protected成员,但其他方法均不能访问
一个子类对象引用可以隐式地转换成一个父类对象引用。使用显式的类型转换,可以把父类引用转换成子类引用。如果目标不是子类对象,将产生ClassCastException例外处理。