java - شرح - كلاسات جافا جاهزة




كيف يمكنني استدعاء مُنشئ واحد من آخر في Java؟ (11)

[ ملاحظة: أريد فقط أن أضيف جانبًا واحدًا ، لم أره في الإجابات الأخرى: كيفية التغلب على قيود متطلبات أن يكون هذا () في السطر الأول). ]

في Java يمكن استدعاء مُنشئ آخر من نفس الفئة من مُنشئ عبر this() . لاحظ مع ذلك أن this يجب أن يكون في السطر الأول.

public class MyClass {

  public MyClass(double argument1, double argument2) {
    this(argument1, argument2, 0.0);
  }

  public MyClass(double argument1, double argument2, double argument3) {
    this.argument1 = argument1;
    this.argument2 = argument2;
    this.argument3 = argument3;
  }
}

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

public class MyClass {

  public MyClass(double argument1, double argument2) {
    this(argument1, argument2, getDefaultArg3(argument1, argument2));
  }

  public MyClass(double argument1, double argument2, double argument3) {
    this.argument1 = argument1;
    this.argument2 = argument2;
    this.argument3 = argument3;
  }

  private static double getDefaultArg3(double argument1, double argument2) {
    double argument3 = 0;

    // Calculate argument3 here if you like.

    return argument3;

  }

}

هل من الممكن استدعاء مُنشئ من آخر (ضمن نفس الفئة ، وليس من فئة فرعية)؟ إذا نعم كيف؟ وماذا يمكن أن يكون أفضل طريقة لاستدعاء منشئ آخر (إذا كان هناك العديد من الطرق للقيام بذلك)؟


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

    import java.util.*;
    import java.lang.*;

    class Test
    {  
        public static void main(String args[])
        {
            Dog d = new Dog(); // Both Calling Same Constructor of Parent Class i.e. 0 args Constructor.
            Dog cs = new Dog("Bite"); // Both Calling Same Constructor of Parent Class i.e. 0 args Constructor.

            // You need to Explicitly tell the java compiler to use Argument constructor so you need to use "super" key word
            System.out.println("------------------------------");
            Cat c = new Cat();
            Cat caty = new Cat("10");

            System.out.println("------------------------------");
            // Self s = new Self();
            Self ss = new Self("self");
        }
    }

    class Animal
    {
        String i;

        public Animal()
        {
            i = "10";
            System.out.println("Animal Constructor :" +i);
        }
        public Animal(String h)
        {
            i = "20";
            System.out.println("Animal Constructor Habit :"+ i);
        }
    }

    class Dog extends Animal
    {
        public Dog()
        {
            System.out.println("Dog Constructor");
        }
        public Dog(String h)
        {
            System.out.println("Dog Constructor with habit");
        }
    }

    class Cat extends Animal
    {
        public Cat()
        {
            System.out.println("Cat Constructor");
        }
        public Cat(String i)
        {
            super(i); // Calling Super Class Paremetrize Constructor.
            System.out.println("Cat Constructor with habit");
        }
    }

    class Self
    {
        public Self()
        {
            System.out.println("Self Constructor");
        }
        public Self(String h)
        {
            this(); // Explicitly calling 0 args constructor. 
            System.out.println("Slef Constructor with value");
        }
    }

باستخدام this(args) . النمط المفضل هو العمل من أصغر مُنشئ إلى الأكبر.

public class Cons {

 public Cons() {
  // A no arguments constructor that sends default values to the largest
  this(madeUpArg1Value,madeUpArg2Value,madeUpArg3Value);
 }

 public Cons(int arg1, int arg2) {
  // An example of a partial constructor that uses the passed in arguments
  // and sends a hidden default value to the largest
  this(arg1,arg2, madeUpArg3Value);
 }

 // Largest constructor that does the work
 public Cons(int arg1, int arg2, int arg3) {
  this.arg1 = arg1;
  this.arg2 = arg2;
  this.arg3 = arg3;
 }
}

يمكنك أيضًا استخدام طريقة مؤيدة حديثًا للقيمة أو فقط "من":

public class Cons {
 public static Cons newCons(int arg1,...) {
  // This function is commonly called valueOf, like Integer.valueOf(..)
  // More recently called "of", like EnumSet.of(..)
  Cons c = new Cons(...);
  c.setArg1(....);
  return c;
 }
} 

للاتصال بفئة ممتازة ، استخدم super(asdf) . يجب أن تكون المكالمة إلى السوبر هي المكالمة الأولى في المُنشئ أو ستحصل على خطأ في التحويل البرمجي.


بسيط جدا

public class SomeClass{

    int number;
    String someString;

    public SomeClass(){
        number = 0;
    }

    public SomeClass(int number){
        this(); //set the class to 0
        this.setNumber(number); 
    }

    public SomeClass(int number, String someString){
        this(number); //call public SomeClass( int number )
    }

    public void setNumber(int number){
        this.number = number;
    }
    public void setString(String someString){
        this.someString = someString;
    }
    //.... add some accessors
}

الآن هنا بعض الائتمان الإضافي الصغير:

public SomeOtherClass extends SomeClass {
    public SomeOtherClass(int number, String someString){
         super(number, someString); //calls public SomeClass(int number, String someString)
    }
    //.... Some other code.
}

أتمنى أن يساعدك هذا.


عندما أحتاج إلى استدعاء مُنشئ آخر من داخل التعليمة البرمجية (وليس في السطر الأول) ، عادةً ما استخدم طريقة مساعد مثل هذه:

class MyClass {
   int field;


   MyClass() {
      init(0);
   } 
   MyClass(int value) {
      if (value<0) {
          init(0);
      } 
      else { 
          init(value);
      }
   }
   void init(int x) {
      field = x;
   }
}

ولكن في معظم الأحيان أحاول القيام بذلك في الاتجاه الآخر عن طريق استدعاء الصانعين الأكثر تعقيدًا من الأبسطين في السطور الأولى ، إلى أقصى حد ممكن. على سبيل المثال أعلاه

class MyClass {
   int field;

   MyClass(int value) {
      if (value<0)
         field = 0;
      else
         field = value;
   }
   MyClass() {
      this(0);
   }
}

كما قال الجميع بالفعل ، يمكنك استخدام this(…) ، والذي يسمى استدعاء صريح منشئ .

ومع ذلك ، ضع في اعتبارك أنه ضمن بيان الاستدعاء صريح منشئ قد لا تشير إلى

  • أي متغيرات الحالة أو
  • أي طرق سبيل المثال أو
  • أي فصول داخلية معلن عنها في هذه الفئة أو أي طبقة متميزة ، أو
  • this أو
  • super .

كما ورد في JLS (§8.8.7.1).


نعم ، يمكن أن يكون أي عدد من المنشئين موجودًا في فصل ويمكن أن يتم استدعاؤه بواسطة مُنشئ آخر باستخدام this() [الرجاء عدم الخلط بين this() الاتصال بالمنشئ باستخدام this الكلمة الأساسية]. يجب أن يكون this() أو this(args) السطر الأول في المُنشئ.

مثال:

Class Test {
    Test() {
        this(10); // calls the constructor with integer args, Test(int a)
    }
    Test(int a) {
        this(10.5); // call the constructor with double arg, Test(double a)
    }
    Test(double a) {
        System.out.println("I am a double arg constructor");
    }
}

هذا هو المعروف باسم الحمولة الزائدة منشئ.
يرجى ملاحظة أنه بالنسبة للمُنشئ ، لا ينطبق سوى مفهوم الحمولة الزائدة وليس الميراث أو تجاوزه.


نعم من الممكن استدعاء منشئ من آخر. لكن هناك قاعدة لذلك. إذا تم إجراء مكالمة من مُنشئ إلى آخر ، فعندئذٍ

يجب أن يكون استدعاء منشئ جديد عبارة الأول في المنشئ الحالي

public class Product {
     private int productId;
     private String productName;
     private double productPrice;
     private String category;

    public Product(int id, String name) {
        this(id,name,1.0);
    }

    public Product(int id, String name, double price) {
        this(id,name,price,"DEFAULT");
    }

    public Product(int id,String name,double price, String category){
        this.productId=id;
        this.productName=name;
        this.productPrice=price;
        this.category=category;
    }
}

شيء من هذا القبيل أدناه لن ينجح.

public Product(int id, String name, double price) {
    System.out.println("Calling constructor with price");
    this(id,name,price,"DEFAULT");
}

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

مع أحدث java وإضافة lambdas ، من السهل إنشاء مُنشئ يمكنه قبول أي رمز تهيئة تريده.

class LambdaInitedClass {

   public LamdaInitedClass(Consumer<LambdaInitedClass> init) {
       init.accept(this);
   }
}

اتصل بها ...

 new LambdaInitedClass(l -> { // init l any way you want });

يمكن استخدام الكلمة الأساسية هذا لاستدعاء مُنشئ من مُنشئ ، عند كتابة عدة مُنشئ لفئة ، هناك أوقات تريد فيها استدعاء مُنشئ من آخر لتفادي تكرار التعليمات البرمجية.

رفع الصوت عاليا هو الرابط الذي أشرح موضوع آخر حول منشئ و getters () و setters () واستخدمت فئة مع اثنين من الصانعين. آمل أن تكون التوضيحات والأمثلة مفيدة لك.

طرق الضبط أو المنشئات


سأخبرك بطريقة سهلة

هناك نوعان من المنشئات:

  1. منشئ افتراضي
  2. منشئ معتبر

سأشرح في مثال واحد

class ConstructorDemo 
{
      ConstructorDemo()//Default Constructor
      {
         System.out.println("D.constructor ");
      }

      ConstructorDemo(int k)//Parameterized constructor
      {
         this();//-------------(1)
         System.out.println("P.Constructor ="+k);       
      }

      public static void main(String[] args) 
      {
         //this(); error because "must be first statement in constructor
         new ConstructorDemo();//-------(2)
         ConstructorDemo g=new ConstructorDemo(3);---(3)    
       }
   }                  

في المثال أعلاه عرضت 3 أنواع من الاتصال

  1. يجب أن يكون هذا استدعاء () إلى هذا أولاً العبارة في منشئ
  2. هذا هو اسم أقل كائن. هذا تلقائياً باستدعاء منشئ افتراضي. 3. هذا يستدعي المُنَظِر المُعْلَمي.

ملاحظة: يجب أن يكون هذا أول عبارة في المُنشئ.





constructor