継承 Java で別のコンストラクターからコンストラクターを呼び出すにはどうすればよいですか?




暗黙的スーパー コンストラクター object() は未定義です。別のコンストラクターを明示的に呼び出す必要があります (15)

ものすごく単純

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.
}

お役に立てれば。

別のクラスからコンストラクタを呼び出すことは可能ですか(サブクラスではなく同じクラス内で)? はいの場合はどうですか? そして、別のコンストラクタを呼び出す最良の方法は何か(もしそれがいくつかの方法があれば)?


私はあなたに簡単な方法を教えます

コンストラクタには2つのタイプがあります。

  1. デフォルトコンストラクタ
  2. パラメータ化されたコンストラクタ

1つの例で説明します

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. このthis()の呼び出しはコンストラクタの最初の文でなければなりません
  2. これは名前の少ないオブジェクトです。 デフォルトコンストラクタが自動的に呼び出されます。 3.これはParameterizedコンストラクタを呼び出します。

注: これはコンストラクターの最初のステートメントでなければなりません。


これは、テクスコーピングコンストラクタのアンチパターンまたはコンストラクタチェーンと呼ばれます。 はい、間違いなく可能です。 私は上記の多くの例を見ています。あなたは2つまたは3つのコンストラクタだけが必要であることを知っているなら、大丈夫かもしれません。 しかし、もっと必要な場合は、Builderパターンのような異なるデザインパターンを使用してみてください。 例えば:

 public Omar(){};
 public Omar(a){};
 public Omar(a,b){};
 public Omar(a,b,c){};
 public Omar(a,b,c,d){};
 ...

もっと必要な場合があります。 この場合、ビルダーパターンは素晴らしい解決策になります。 ここに記事がありますので参考にしてhttps://medium.com/@modestofiguereo/design-patterns-2-the-builder-pattern-and-the-telescoping-constructor-anti-pattern-60a33de7522e


はい、 this()を使用して別のコンストラクタから1つのコンストラクタを呼び出すことは可能です

class Example{
   private int a = 1;
   Example(){
        this(5); //here another constructor called based on constructor argument
        System.out.println("number a is "+a);   
   }
   Example(int b){
        System.out.println("number b is "+b);
   }

[ 注:私は他の答えには見られなかった1つのアスペクトを追加したいだけです:これは最初の行になければならないという要件の限界を克服する方法です。 ]

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;

  }

}

誰もがすでに言っているように、 this(…)を使用します 。これは、 明示的なコンストラクタ呼び出しと呼ばれます

ただし、このような明示的なコンストラクタ呼び出し文では、参照できないことがあります

  • 任意のインスタンス変数または
  • 任意のインスタンスメソッドまたは
  • このクラスまたはスーパークラスで宣言された内部クラス、または
  • thisまたは
  • super

JLS(§8.8.7.1)に記載されているとおり。


"this"キーワードを使用すると、同じクラスの別のコンストラクタのコンストラクタを使用できます。 例 -

class This1
{
    This1()
    {
        this("Hello");
        System.out.println("Default constructor..");
    }
    This1(int a)
    {
        this();
        System.out.println("int as arg constructor.."); 
    }
    This1(String s)
    {
        System.out.println("string as arg constructor..");  
    }

    public static void main(String args[])
    {
        new This1(100);
    }
}

argコンストラクタとしての出力文字列.. argコンストラクタとしてのデフォルトコンストラクタ.. int


最初の行ではなく、コードの中から別のコンストラクタを呼び出す必要があるときは、通常、次のようなヘルパーメソッドを使用します。

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);
   }
}

複雑な構造の必要性をカバーするデザインパターンがあります。簡潔に行うことができない場合は、ファクトリメソッドまたはファクトリクラスを作成します。

最新のJavaとlambdaの追加により、任意の初期化コードを受け入れるコンストラクタを作成するのは簡単です。

class LambdaInitedClass {

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

それと呼んで...

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

はい、あるコンストラクタを別のコンストラクタから呼び出すことは可能です。 しかしそれには規則があります。 あるコンストラクタから別のコンストラクタへの呼び出しが行われた場合、

その新しいコンストラクタ呼び出しは、現在のコンストラクタの最初の文でなければなりません

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");
}

また、継承の場合、サブクラスのオブジェクトが作成されると、スーパークラスのコンストラクタが最初に呼び出されます。

public class SuperClass {
    public SuperClass() {
       System.out.println("Inside super class constructor");
    }
}
public class SubClass extends SuperClass {
    public SubClass () {
       //Even if we do not add, Java adds the call to super class's constructor like 
       // super();
       System.out.println("Inside sub class constructor");
    }
}

したがって、この場合、別のコンストラクター呼び出しも最初に他のステートメントの前に宣言されます。


はい、可能です:

public class Foo {
    private int x;

    public Foo() {
        this(1);
    }

    public Foo(int x) {
        this.x = x;
    }
}

同じクラスのものではなく、特定のスーパークラスのコンストラクタに連結するには、 this代わりにsuperを使用します。 1つのコンストラクターにのみ連結でき 、コンストラクター本体の最初のステートメントで なければならないことに注意してください

C# に関するこの同じ質問を参照してください。ただし、同じ原則が適用されます。


this(...)キーワード(同じクラスからコンストラクタを呼び出す必要がある場合)またはsuper(...)キーワード( super(...)クラスからコンストラクタを呼び出す必要がある場合this(...)を使用して、別のコンストラクタを呼び出すことができます。

しかし、そのような呼び出しは、コンストラクターの最初のステートメントでなければなりません。 この制限を克服するには 、 この回答を使用してください 。


this(args)を使う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;
 }
}

さらに最近に提唱されたvalueOfのアプローチ、または単に "of"のアプローチを使うこともできます:

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 super(someValue)使用します。 superへの呼び出しは、コンストラクターの最初の呼び出しでなければなりません。そうしないと、コンパイラー・エラーが発生します。


別のコンストラクタからコンストラクタを呼び出す

class MyConstructorDemo extends ConstructorDemo
{
    MyConstructorDemo()
    {
        this("calling another constructor");
    }
    MyConstructorDemo(String arg)
    {
        System.out.print("This is passed String by another constructor :"+arg);
    }
}

また、 super()コンストラクターをsuper()呼び出しを使用して呼び出すこともできます


thisキーワードは、コンストラクタからコンストラクタを呼び出すために使用できます。クラスのコンストラクタをいくつか記述すると、重複したコードを避けるために別のコンストラクタから1つのコンストラクタを呼び出すことができます。

Bellowは、コンストラクタとgetters()とsetters()について他のトピックを説明するリンクで、2つのコンストラクタを持つクラスを使用しました。 説明と例があなたに役立つことを願っています。

セッターメソッドまたはコンストラクター





constructor