CodeGym /مدونة جافا /Random-AR /تسلسل الإجراءات أثناء إنشاء الكائن
John Squirrels
مستوى
San Francisco

تسلسل الإجراءات أثناء إنشاء الكائن

نشرت في المجموعة
أهلاً! درس اليوم سيكون إلى حد ما... أه... متعدد الأوجه :) بمعنى أننا سنغطي مجموعة واسعة من المواضيع، ولكنها جميعها ستتعلق بعملية إنشاء الكائنات . تسلسل الإجراءات أثناء إنشاء الكائن - 1سنقوم بتحليلها من البداية إلى النهاية: كيف يتم استدعاء المُنشئين، وكيف وبأي ترتيب تتم تهيئة الحقول (بما في ذلك الحقول الثابتة)، وما إلى ذلك. لقد تطرقنا سابقًا إلى بعض النقاط التي تمت مناقشتها في المقالة، حتى تتمكن من إلقاء نظرة سريعة عليها المواد على منشئي الطبقة الأساسية . أولاً، دعونا نتذكر كيفية إنشاء الكائن. تتذكر جيدًا كيف تبدو هذه العملية من وجهة نظر المطور: يقوم بإنشاء فصل، ويكتب new، وكل شيء جاهز :) هنا سنتحدث عما يحدث داخل الكمبيوتر وجهاز Java عندما نكتب، على سبيل المثال:
Cat cat = new Cat();
لقد تحدثنا عن هذا من قبل، ولكن فقط في حالة سنذكرك:
  • أولا، يتم تخصيص الذاكرة لتخزين الكائن.
  • بعد ذلك، تقوم آلة Java بإنشاء مرجع للكائن (في حالتنا، المرجع هو Cat cat).
  • وأخيرا، تتم تهيئة المتغيرات ويتم استدعاء المنشئ (سننظر في هذه العملية بمزيد من التفصيل).
بالإضافة إلى ذلك، من الدرس الخاص بدورة حياة الكائن ، ربما تتذكر أن الكائن يستمر طالما أن هناك مرجعًا واحدًا له على الأقل. إذا لم يبق شيء، يصبح الكائن فريسة لجامع القمامة. تسلسل الإجراءات أثناء إنشاء الكائن - 2لا ينبغي أن تثير هاتان النقطتان الأوليتان أي أسئلة خاصة. يعد تخصيص الذاكرة عملية بسيطة، وهناك نتيجتان محتملتان فقط: إما أن تكون هناك ذاكرة أو لا توجد :) وإنشاء رابط ليس بالأمر غير المعتاد. لكن النقطة الثالثة تمثل مجموعة كاملة من العمليات التي يتم تنفيذها بترتيب صارم. أنا لست من محبي تكثيف الاختبارات، لكن عليك أن تفهم هذه العملية جيدًا وتحتاج إلى حفظ تسلسل العمليات هذا . عندما تحدثنا عن عملية إنشاء الكائنات في الدروس السابقة، لم تكن تعرف أي شيء عن الميراث بعد، لذلك كان شرح بعض الأشياء مشكلة. الآن أنت تعرف الكثير ويمكننا أخيرًا النظر في هذا السؤال بالكامل :) إذن النقطة الثالثة تقول " أخيرًا، تتم تهيئة المتغيرات ويتم استدعاء المنشئ. " ولكن بأي ترتيب يحدث كل هذا؟ للحصول على فهم أفضل، دعونا ننشئ فصلين بسيطين للغاية — أحد الوالدين والطفل:
public class Vehicle {

   public static int vehicleCounter = 0;

   private String description = "Vehicle";
   public Vehicle() {
   }

   public String getDescription() {
       return description;
   }
}

public class Truck extends Vehicle {

   private static int truckCounter = 0;

   private int yearOfManufacture;
   private String model;
   private int maxSpeed;

   public Truck(int yearOfManufacture, String model, int maxSpeed) {
       this.yearOfManufacture = yearOfManufacture;
       this.model = model;
       this.maxSpeed = maxSpeed;

       Vehicle.vehicleCounter++;
       truckCounter++;
   }
}
الفصل Truckعبارة عن تطبيق لشاحنة تحتوي على حقول تمثل عامها وطرازها وسرعتها القصوى. الآن نريد إنشاء كائن واحد من هذا القبيل:
public class Main {

   public static void main(String[] args) throws IOException {

       Truck truck = new Truck(2017, "Scania S 500 4x2", 220);
   }
}
بالنسبة لجهاز جافا، ستبدو العملية كما يلي:
  1. أول ما يحدث هو تهيئة المتغيرات الثابتة للفئةVehicle . نعم، قلت الطبقة Vehicle، وليس Truck. تتم تهيئة المتغيرات الثابتة قبل استدعاء المنشئات، ويبدأ ذلك في الفئة الأصل. دعونا نحاول التحقق من ذلك. قمنا بتعيين vehicleCounterالحقل في Vehicleالفصل على 10 وحاول عرضه في كل من Vehicleالمنشئين Truck.

    public class Vehicle {
    
       public static int vehicleCounter = 10;
       private String description = "Vehicle";
    
       public Vehicle() {
           System.out.println(vehicleCounter);
       }
    
       public String getDescription() {
           return description;
       }
    }
    
    public class Truck extends Vehicle {
    
       private static int truckCount = 0;
    
       private int yearOfManufacture;
       private String model;
       private int maxSpeed;
    
       public Truck(int yearOfManufacture, String model, int maxSpeed) {
           System.out.println(vehicleCounter);
           this.yearOfManufacture = yearOfManufacture;
           this.model = model;
           this.maxSpeed = maxSpeed;
    
           Vehicle.vehicleCounter++;
           truckCount++;
       }
    }

    لقد وضعنا عبارة println عمدًا في بداية المُنشئ Truckللتأكد من أن حقول الشاحنة لم تتم تهيئتها بعد عند vehicleCounterعرضها.

    وهذه هي النتيجة:

    10
    10
  2. بعد تهيئة المتغيرات الثابتة للفئة الأصلية، تتم تهيئة المتغيرات الثابتة للفئة الفرعية. في حالتنا، هذا هو truckCounterمجال الطبقة Truck.

    لنقم بتجربة أخرى حيث سنحاول عرض قيمة truckCounterداخل Truckالمُنشئ قبل تهيئة الحقول الأخرى:

    public class Truck extends Vehicle {
    
       private static int truckCounter = 10;
    
       private int yearOfManufacture;
       private String model;
       private int maxSpeed;
    
       public Truck(int yearOfManufacture, String model, int maxSpeed) {
           System.out.println(truckCounter);
           this.yearOfManufacture = yearOfManufacture;
           this.model = model;
           this.maxSpeed = maxSpeed;
    
           Vehicle.vehicleCounter++;
           truckCounter++;
       }
    }

    كما ترون، تم بالفعل تعيين القيمة 10 للمتغير الثابت لدينا عندما Truckيبدأ المنشئ.

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

    كتجربة، يمكننا تعيين بعض القيمة الأولية للمتغير descriptionفي Vehicleالفئة، ثم تغييرها في المنشئ.

    public class Vehicle {
    
       public static int vehicleCounter = 10;
    
       private String description = "Initial value of the description field";
    
       public Vehicle() {
           System.out.println(description);
           description = "Vehicle";
           System.out.println(description);
       }
    
       public String getDescription() {
           return description;
       }
    }

    لنقم بتشغيل main()طريقتنا لإنشاء شاحنة:

    public class Main {
    
       public static void main(String[] args) throws IOException {
    
           Truck truck = new Truck(2017, "Scania S 500 4x2", 220);
       }
    }

    نحصل على النتيجة التالية:

    
    Initial value of the description field 
    Vehicle

    وهذا يثبت أنه عندما Vehicleيبدأ المنشئ، descriptionتم بالفعل تعيين قيمة للحقل.

  4. أخيرا، حان الوقت للبناة! بتعبير أدق، حان الوقت لمنشئ الطبقة الأساسية. يتم استدعاؤه في الخطوة الرابعة من عملية إنشاء الكائن.

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

    public Vehicle() {
    
       System.out.println("Hello from the Vehicle constructor!");
    }
    
    public Truck(int yearOfManufacture, String model, int maxSpeed) {
    
       System.out.println("Hello from the Truck constructor!");
       this.yearOfManufacture = yearOfManufacture;
       this.model = model;
       this.maxSpeed = maxSpeed;
    
       Vehicle.vehicleCounter++;
       truckCounter++;
    }

    سنقوم بتشغيل طريقتنا main()وننظر إلى النتيجة:

    Hello from the Vehicle constructor!
    Hello from the Truck constructor!

    ممتاز. وهذا يعني أننا لسنا مخطئين :) دعونا نمضي قدما.

  5. حان الوقت الآن لتهيئة الحقول غير الثابتة للفصل الفرعي، أي فصلنا Truck. لا تتم تهيئة الحقول الموجودة مباشرة داخل الفصل الذي يتم إنشاء مثيل له حتى الخطوة الخامسة! مفاجئ، ولكنه حقيقي :) مرة أخرى، سنجري فحصًا بسيطًا - تمامًا كما هو الحال مع الفئة الأصلية: سنضع بعض القيمة الأولية للمتغير maxSpeedوفي Truckالمنشئ سنتحقق من أنه تم تعيين القيمة قبل بدء المنشئ:

    public class Truck extends Vehicle {
    
       private static int truckCounter = 10;
    
       private int yearOfManufacture;
       private String model;
       private int maxSpeed = 150;
    
       public Truck(int yearOfManufacture, String model, int maxSpeed) {
    
           System.out.println("Initial value of maxSpeed = " + this.maxSpeed);
           this.yearOfManufacture = yearOfManufacture;
           this.model = model;
           this.maxSpeed = maxSpeed;
    
           Vehicle.vehicleCounter++;
           truckCounter++;
       }
    }

    إخراج وحدة التحكم:

    Initial value of maxSpeed = 150

    كما ترون،  عندما Truck يبدأ المنشئ، maxSpeed يساوي بالفعل 150!

  6. Truckيتم استدعاء منشئ فئة الطفل.

    وفقط عند هذه النقطة، أخيرًا، سيتم استدعاء منشئ الفئة التي نقوم بإنشاء مثيل لها!

    فقط في الخطوة السادسة سيتم تخصيص القيم التي نمررها إلى شاحنتنا للحقول.

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

تسلسل الإجراءات أثناء إنشاء الكائن - 3 لماذا من المهم جدًا فهم هذه العملية جيدًا؟ تخيل كيف يمكن أن تكون نتائج إنشاء كائن عادي غير متوقعة إذا كنت لا تعرف بالضبط ما كان يحدث "تحت الغطاء" :) الآن حان وقت العودة إلى الدورة التدريبية وإكمال بعض المهام! حظا سعيدا ونراكم قريبا! :)
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION