سؤال

ما هو الفرق بين هذه التصريحين Innerclass؟ أيضا التعليق على المزايا / العيوب؟

الحالة A: فئة داخل الفصل.

public class Levels {   
  static public class Items {
    public String value;
    public String path;

    public String getValue() {
      return value;}
  }
}

والحالة ب: الطبقة داخل الواجهة.

public interface Levels{

  public class Items {
    public String value;
    public String path;

    public String getValue() {
      return value;}
  }
}

تصحيح الصنع: لوضع طريقة GetValue.

مزيد من المعلومات: أنا قادر على إنشاء فئة البنود في كلتا الحالتين A و B في فئة أخرى لا تنفذ واجهة على الإطلاق.

public class Z{//NOTE: NO INTERFACE IMPLEMENTED here!!!!
 Levels.Items items = new Levels.Items();
}

نظرا لأن الواجهة غير مثبتة، إلا أن جميع العناصر الموجودة داخل الواجهة يمكن الوصول إليها بواسطة مدوع DOT بدون مستويات Instalface مثبتة ببساطة لأنك لا تستطيع إنشاء إنشاء واجهة - بفعالية جعل فئة محددة داخل واجهة نادرة مرجعية ثابتة.

لذا قل أن العناصر البنود في حالة ب ليس ثابتا لا معنى له. بما أن كلتا الحالتين A و B مثبتة بنفس الطريقة، فإنني لا أبحث عن دلالات حول ما هو ثابت أو داخلية أو متداخلة. التوقف عن إعطائي إجابات على دلالات. أريد المحول البرمجي أو الاختلافات في وقت التشغيل والسلوكية / المزايا، أو إذا لم يقل أي شيء. لا مزيد من الإجابات على دلالات من فضلك! خبير في مواصفات JVM أو .NET VM Intoards، يرجى السؤال الإجابة بدلا من كتاب Semanticiests.

هل كانت مفيدة؟

المحلول

غالبا ما تشبه الطبقات الداخلية الثابتة فئات المستوى الأعلى، باستثناء الطبقة الداخلية لديها الوصول إلى جميع ثابتة المتغيرات وطرق الطبقة المرفوعة. يتم إلحاق اسم الفئة المحيط بشكل فعال إلى مساحة اسم الحزمة للطبقة الداخلية. بإعلان وجود فئة كطبقة داخلية ثابتة، فأنت تقوم بالتواصل أن الفصل مرتبط بطريقة أو بأخرى في سياق الفئة المرفوعة.

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

Levels levels = new Levels(); // first need an instance of the enclosing class

// The items object contains an implicit reference to the levels object
Levels.Items items  = levels.new Items(); 

تعتبر الطبقات الداخلية غير الثابتة أكثر صعوبة بكثير إلى دروسها المرفوعة منها من الطبقات الداخلية الثابتة. لديهم استخدامات صالحة (على سبيل المثال، غالبا ما يتم تنفيذ المحامين كصفات فئات داخلية غير ثابتة داخل فئة بنية البيانات التي تتسبب في تكرارها).

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

نصائح أخرى

أ static الطبقة الداخلية هي فئة متداخلة، وتسمى غير ثابتة من الطبقة الداخلية. للمزيد من، انظر هنا.

ومع ذلك، أحب أن أقتبس مقتطف من نفس الرابط.

يتفاعل فئة متداخلة ثابتة مع أفراد مثيل الطبقة الخارجية (وغيرها من الفصول) مثل أي فئة أعلى مستوى أعلى. في الواقع، يتمثل فئة متداخلة ثابتة في السلوك فئة المستوى الأعلى تم تداخلها في فئة أخرى أعلى مستوى للتعبئة والتغليف.

أنت لم تستخدم الكلمة static في الحالة الثانية. وتعتقد أنها ستكون ضمنيا static لأنها واجهة. أنت على حق في افتراض ذلك.

يمكنك إنشاء إنشاء الفئة الداخلية في واجهتك، تماما مثل فئة متداخلة ثابتة، لأنها حقا static فئة متداخلة.

Levels.Items hello = new Levels.Items();

لذلك، سيكون البيان أعلاه صالح في كل من حالاتك. وبعد حالتك الأولى هي من فئة متداخلة ثابتة، وفي الحالة الثانية التي لم تحددها static, ، ولكن حتى ذلك الحين سيكون فئة متداخلة ثابتة لأنها في الواجهة. وبالتالي، لا يوجد فرق آخر ثم حقيقة أنه يتغير المرء في الفصل، والآخر في واجهة.

عادة فئة داخلية في الفصل، ليس في واجهة, ، سوف تكون مثيل لها مثل أدناه.

Levels levels = new Levels();
Levels.Items items = levels.new Items();

علاوة على ذلك، فإن الطبقة الداخلية "غير الثابتة" ستكون مرجعا ضمنيا إلى فئةها الخارجية. هذا ليس هو الحال مع فئة متداخلة "ثابتة".

إذا كنت تعلن فئة متداخلة في واجهة، فهي دائما عامة و ثابتة. وبعد وبالتالي:

public interface Levels{
    class Items {
        public String value;
        public String path;

        public String getValue() {return value;}
    }
}

هو بالضبط نفس

public interface Levels{
    public static class Items {
        public String value;
        public String path;

        public String getValue() {return value;}
    }
}

وحتى

public interface Levels{
    static class Items {
        public String value;
        public String path;

        public String getValue() {return value;}
    }
}

لقد راجعت هذا مع Javap -verbosebose وكلهم ينتجون

Compiled from "Levels.java"
public class Levels$Items extends java.lang.Object
  SourceFile: "Levels.java"
  InnerClass: 
   public #14= #3 of #23; //Items=class Levels$Items of class Levels
  minor version: 0
  major version: 50
  Constant pool:
const #1 = Method   #4.#21; //  java/lang/Object."<init>":()V
const #2 = Field    #3.#22; //  Levels$Items.value:Ljava/lang/String;
const #3 = class    #24;    //  Levels$Items
const #4 = class    #25;    //  java/lang/Object
const #5 = Asciz    value;
const #6 = Asciz    Ljava/lang/String;;
const #7 = Asciz    path;
const #8 = Asciz    <init>;
const #9 = Asciz    ()V;
const #10 = Asciz   Code;
const #11 = Asciz   LineNumberTable;
const #12 = Asciz   LocalVariableTable;
const #13 = Asciz   this;
const #14 = Asciz   Items;
const #15 = Asciz   InnerClasses;
const #16 = Asciz   LLevels$Items;;
const #17 = Asciz   getValue;
const #18 = Asciz   ()Ljava/lang/String;;
const #19 = Asciz   SourceFile;
const #20 = Asciz   Levels.java;
const #21 = NameAndType #8:#9;//  "<init>":()V
const #22 = NameAndType #5:#6;//  value:Ljava/lang/String;
const #23 = class   #26;    //  Levels
const #24 = Asciz   Levels$Items;
const #25 = Asciz   java/lang/Object;
const #26 = Asciz   Levels;

{
public java.lang.String value;

public java.lang.String path;

public Levels$Items();
  Code:
   Stack=1, Locals=1, Args_size=1
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return
  LineNumberTable: 
   line 2: 0

  LocalVariableTable: 
   Start  Length  Slot  Name   Signature
   0      5      0    this       LLevels$Items;


public java.lang.String getValue();
  Code:
   Stack=1, Locals=1, Args_size=1
   0:   aload_0
   1:   getfield    #2; //Field value:Ljava/lang/String;
   4:   areturn
  LineNumberTable: 
   line 7: 0

  LocalVariableTable: 
   Start  Length  Slot  Name   Signature
   0      5      0    this       LLevels$Items;


}

الأمثلة التي تقدمها من الطبقات المتداخلة / IMO) أمثلة سيئة. إلى جانب المثال الثاني غير صحيح Java منذ واجهة يمكن أن تعلن فقط (ضمنيا) طرق مجردة. إليك مثال أفضل:

public interface Worker {

    public class Response {
        private final Status status;
        private final String message;
        public Response(Status status, String message) {
            this.status = status; this.message = message;
        }
        public Status getStatus() { return status; }
        public String getMessage() { return message; }
    }

    ...

    public Response doSomeOperation(...);
}

من خلال تضمين فئة الاستجابة، نشير إلى أنه جزء أساسي من Worker API بدون استخدامات أخرى.

The Map.Entry Class هو مثال معروف على هذا المصطلح.

IMHO، مميزات هل حصلت على عدد أقل من الفئات تشوش مجلد المشروع الخاص بك إذا كانت تافهة؛ ال غير مؤات هو أنه عندما تنمو الطبقة الداخلية الخاصة بك على طول متطلبات التغيير، صيانة تصبح كابوسك.

اعتقدت أن أول واحد سيذكر مستويات فئة وطبقة داخلية ثابتة تسمى البنود. يمكن الإشارة عن العناصر بالمستويات. وستكون ثابتة.

في حين أن الثانية من شأنها أن تعلن الطبقة الداخلية البسيطة، والتي يمكن الوصول إليها باستخدام المستويات.

Levels.Items hello = new Levels.Items();

تحرير: هذا خطأ تماما، وقراءة التعليقات والردود الأخرى.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top