Как я могу использовать несколько конструкторов для удаления дублированного кода при сохранении читаемости?
int a, b, c;
Constructor()
{
a = 5;
b = 10;
c = 15;
//do stuff
}
Constructor(int x, int y)
{
a = x;
b = y;
c = 15;
//do stuff
}
Constructor(int x, int y, int z)
{
a = x;
b = y;
c = z;
//do stuff
}
Чтобы предотвратить дублирование "материала" и нескольких заданий, я попробовал что-то вроде:
int a, b, c;
Constructor(): this(5, 10, 15)
{
}
Constructor(int x, int y): this(x, y, 15)
{
}
Constructor(int x, int y, int z)
{
a = x;
b = y;
c = z;
//do stuff
}
Это работает для того, что я хочу делать, но иногда мне нужно использовать какой-то длинный код для создания новых объектов или выполнения некоторых вычислений:
int a, b, c;
Constructor(): this(new Something(new AnotherThing(param1, param2, param3),
10, 15).CollectionOfStuff.Count, new SomethingElse("some string", "another
string").GetValue(), (int)Math.Floor(533 / 39.384))
{
}
Constructor(int x, int y): this(x, y, (int)Math.Floor(533 / 39.384))
{
}
Constructor(int x, int y, int z)
{
a = x;
b = y;
c = z;
//do stuff
}
Этот код почти такой же, как и раньше, только те параметры, которые передаются, не очень читаемы. Я бы предпочел сделать что-то вроде:
int a, b, c;
Constructor(): this(x, y, z) //compile error, variables do not exist in context
{
AnotherThing at = new AnotherThing(param1, param2, param3);
Something st = new Something(aThing, 10, 15)
SomethingElse ste = new SomethingElse("some string", "another string");
int x = thing.CollectionOfStuff.Count;
int y = ste.GetValue();
int z = (int)Math.Floor(533 / 39.384);
//In Java, I think you can call this(x, y, z) at this point.
this(x, y, z); //compile error, method name expected
}
Constructor(int x, int y): this(x, y, z) //compile error
{
int z = (int)Math.Floor(533 / 39.384);
}
Constructor(int x, int y, int z)
{
a = x;
b = y;
c = z;
//do stuff
}
В основном я строю параметры внутри тела конструктора. Затем я пытаюсь передать эти встроенные параметры другому конструктору. Я думаю, что я помню, как можно было использовать ключевые слова "this" и "super" для вызова конструкторов, а внутри тела другого конструктора при кодировании на Java. Это не похоже на С#.
Есть ли способ сделать это легко? Я сделал что-то неправильно? Если это невозможно, я должен просто придерживаться нечитаемого кода?
Думаю, я всегда мог вырезать дублированный код в другой метод, полностью вне конструкторов. Тогда каждый конструктор просто выполнит свою собственную задачу и вызовет код, разделяемый другими конструкторами.
Ответы
Ответ 1
В качестве альтернативы вызову метода инициализации из всех конструкторов (который запрещает использование полей readonly
) или factory (которые вводят дополнительную сложность при создании классов), вы можете использовать объект параметра:
int a, b, c;
public Constructor()
: this(new ConstructorParameters())
{
}
public Constructor(int x, int y)
: this(new ConstructorParameters(x, y))
{
}
public Constructor(int x, int y, int z)
{
a = x;
b = y;
c = z;
//do stuff
}
private Constructor(ConstructorParameters parameters)
: this(parameters.X, parameters.Y, parameters.Z)
{
}
private class ConstructorParameters
{
public int X;
public int Y;
public int Z;
public ConstructorParameters()
{
AnotherThing at = new AnotherThing(param1, param2, param3);
Something st = new Something(at, 10, 15)
SomethingElse ste = new SomethingElse("some string", "another string");
X = st.CollectionOfStuff.Count;
Y = ste.GetValue();
Z = (int)Math.Floor(533 / 39.384);
}
public ConstructorParameters(int x, int y)
{
X = x;
Y = y;
Z = (int)Math.Floor(533 / 39.384);
}
}
Ответ 2
Вы можете сделать
Constructor() : this(5, 10, 15)
{
}
Constructor(int x, int y) : this(x, y, 15)
{
}
Constructor(int x, int y, int z)
{
int a = x;
int b = y;
int c = z;
//do stuff
}
Однако, если вам нужно сделать какую-нибудь причудливую логику в зависимости от параметров, я бы использовал шаблон factory:
public class myclass
{
private myclass(int x, int y, int z)
{
int a = x;
int b = y;
int c = z;
//do stuff
}
public static myclass Create()
{
AnotherThing at = new AnotherThing(param1, param2, param3);
Something st = new Something(aThing, 10, 15)
SomethingElse ste = new SomethingElse("some string", "another string");
int x = thing.CollectionOfStuff.Count;
int y = ste.GetValue();
int z = (int)Math.Floor(533 / 39.384);
return new myclass(x, y ,z);
}
public static myclass Create(int x, int y)
{
if (x = 1)
return new myclass(x, y, 2)
else
return new myclass(x, y, 15);
}
public static myclass Create(int x, int y, int z)
{
//so on and so forth
return new myclass(x, y, z);
}
}
Хотя вам не нужен шаблон factory, он определенно делает вашу конструкторную логику доступной для чтения.