Перегруженный конструктор вызывает другой конструктор, но не как первый оператор
У меня возникли проблемы с использованием нескольких конструкторов в java.
что я хочу сделать, это примерно так:
public class MyClass {
// first constructor
public MyClass(arg1, arg2, arg3) {
// do some construction
}
// second constructor
public MyClass(arg1) {
// do some stuff to calculate arg2 and arg3
this(arg1, arg2, arg3);
}
}
но я не могу, поскольку второй конструктор не может вызвать другой конструктор, если он не является первой строкой.
Какое общее решение для такой ситуации?
Я не могу вычислить arg2 и arg3 "в строке". Я подумал, может быть, создание метода вспомогательного строительства, который будет выполнять фактическую конструкцию, но я не уверен, что так "красиво"...
EDIT. Использование вспомогательного метода также проблематично, поскольку некоторые из моих полей являются окончательными, и я не могу установить их с помощью вспомогательного метода.
Ответы
Ответ 1
Как правило, используйте другой общий метод - "помощник по строительству", который вы предложили.
public class MyClass {
// first constructor
public MyClass(arg1, arg2, arg3) {
init(arg1, arg2, arg3);
}
// second constructor
public MyClass(int arg1) {
// do some stuff to calculate arg2 and arg3
init(arg1, arg2, arg3);
}
private init(int arg1, int arg2, int arg3) {
// do some construction
}
}
Альтернативой является Factory -стильный подход, в котором у вас есть MyClassFactory
, который дает вам экземпляры MyClass
, а MyClass
имеет только один конструктор:
public class MyClass {
// constructor
public MyClass(arg1, arg2, arg3) {
// do some construction
}
}
public class MyClassFactory {
public static MyClass MakeMyClass(arg1, arg2, arg3) {
return new MyClass(arg1, arg2, arg3);
}
public static MyClass MakeMyClass(arg1) {
// do some stuff to calculate arg2 and arg3
return new MyClass(arg1, arg2, arg3);
}
}
Я определенно предпочитаю первый вариант.
Ответ 2
Следующее возможное решение - Factory метод. Эти статические методы могут быть перегружены, и после вычисления они могут вызывать частный/защищенный конструктор
public class MyClass {
private MyClass( arg1, arg2, arg3 ) {
// do sth
}
public static MyClass getInstance( arg1 ) {
// calculate arg2,3
return new MyClass( arg1, arg2, arg3 );
}
public static MyClass getInstance( arg1, arg2, arg3 ) {
return new MyClass( arg1, arg2, arg3 );
}
}
EDIT: Этот метод также идеален, если у вас есть окончательные поля
Ответ 3
Хотя я предпочитаю вариант метода factory, на который указывают несколько других ответов, я хотел предложить другой вариант: вы можете использовать статические методы для вычисления других параметров:
public class MyClass {
public MyClass(int arg1, int arg2, int arg3) {
// do some construction
}
public MyClass(int arg1) {
//call to this() must be the first one
this(arg1, calculateArg2(arg1), calculateArg3());
//you can do other stuff here
}
private static int calculateArg2(int arg1) {
//calc arg2 here
}
private static int calculateArg3() {
//calc arg3 here
}
}
Ответ 4
Параметры помощника и factory очень хороши.
Есть еще один:
public MyClass(int arg1) {
this(arg1, calculateArg2(), calculateArg3());
}
private static int calculateArg2() {..}
private static int calculateArg3() {..}
Ответ 5
Использовать значения маркера для 'missing'
public class MyClass {
public MyClass(arg1, arg2, arg3) {
// do some stuff to calculate arg2 and arg3 if they are the missing values
// do some construction
}
public MyClass(arg1) {
this(arg1, null, null);
}
}
Для достижения наилучших результатов создайте "общий" конструктор protected
или private
.
Ответ 6
Вы можете переместить код MyClass(arg1, arg2, arg3)
в вспомогательный метод (name it Init
или что-то еще), а затем вызвать этот метод в обоих конструкторах.
Ответ 7
Вы можете создать factory метод, который вызывает конструктор:
public class MyClass {
// first constructor
public MyClass(arg1, arg2, arg3) {
// do some construction
}
// second constructor as factory method
public static createMyClassAndDoFunkyStuff(int arg1) {
// do some stuff to calculate arg2 and arg3
return new MyClass(arg1, arg2, arg3);
}
}
Ответ 8
Другой способ:
public class MyClass {
// first constructor
public MyClass(arg1, arg2, arg3) {
// do some construction
doSomeStuffToArg3Arg3(arg2, arg3)
}
// second constructor
public MyClass(int arg1) {
this(arg1, arg2, arg3);
}
private void doSomeStuffToArg3Arg3(int arg2, int arg3) {
// do some stuff to calculate arg2 and arg3
}
}
Ответ 9
В качестве альтернативы приведенным ответам наиболее простым способом является рефакторинг вычисления аргумента в конструкторе аргументов 3;
public class MyClass {
// first constructor
public MyClass(arg1, arg2, arg3) {
if (null == arg2) {
// calculate arg2
}
if (null == arg3) {
// calculate arg3
}
// do some construction
}
// second constructor
public MyClass(arg1) {
this(arg1, null, null);
}
}