我想定义一个辅助构造函数,它应该计算一些值并在传递给主构造函数的多个参数中使用它。表达这一点的一种自然方式是在调用主构造函数之前定义局部值,但语言不允许这样做:
public class MainActivity extends AppCompatActivity {
RelativeLayout container;
int cellWidth = 0, cellHeight = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
tableLayout.setStretchAllColumns(true);
for (int i = 0; i < 4; i++) {
TableRow tableRow = new TableRow(this);
for (int j = 0; j < 10; j++) {
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View cell = layoutInflater.inflate(R.layout.table_cell, null, false);
if (cellHeight == 0 ) {
cell.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
cellWidth = cell.getMeasuredWidth();
cellHeight = cell.getMeasuredHeight();
}
tableRow.addView(cell);
}
tableLayout.addView(tableRow);
}
container = (RelativeLayout)findViewById(R.id.container);
overlappingImage = new ImageView(this);
overlappingImage.setScaleType(ImageView.ScaleType.FIT_XY);
}
ImageView overlappingImage;
private void restoreTableLayout() {
container.removeView(overlappingImage);
}
public void onClick11(View view) {
restoreTableLayout();
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(cellWidth, cellHeight);
overlappingImage.setLayoutParams(params);
overlappingImage.setImageResource(R.drawable.horizontal_cat);
container.addView(overlappingImage);
}
public void onClick41(View view) {
restoreTableLayout();
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(cellWidth*4, cellHeight);
overlappingImage.setLayoutParams(params);
overlappingImage.setImageResource(R.drawable.horizontal_cat);
container.addView(overlappingImage);
}
public void onClick32(View view) {
restoreTableLayout();
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(cellWidth*3, cellHeight*2);
params.setMargins(cellWidth*2, cellHeight*2, 0 ,0);
overlappingImage.setLayoutParams(params);
overlappingImage.setImageResource(R.drawable.vertical_cat);
container.addView(overlappingImage);
}
public void onClick22(View view) {
restoreTableLayout();
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(cellWidth*2, cellHeight*2);
overlappingImage.setLayoutParams(params);
overlappingImage.setImageResource(R.drawable.horizontal_cat);
container.addView(overlappingImage);
}
}
另一种方法是重复计算,但是由于计算非常复杂,这可能是一个问题(并且还会导致代码重复):
object Computed {
def veryComplexComputation(x: Double) = math.sqrt(x) // imagine there is some much more complex computation here
}
class Computed(x: Double, y: Double, z: Double) {
def this(x: Double, y: Double) = {
val derivedFromX = Computed.veryComplexComputation(x)
val derivedFromY = derivedFromX * Computed.veryComplexComputation(y)
this(x, derivedFromX, derivedFromY)
}
}
答案 0 :(得分:2)
我知道的最好的技巧是使用第三个,私有构造函数,为主构造函数提供参数元组,以及随播对象中的辅助函数:
object Computed {
def veryComplexComputation(x: Double) = math.sqrt(x) // imagine there is some much more complex computation here
private def computeArgs(x: Double, y: Double): (Double, Double, Double) = {
val derivedFromX = veryComplexComputation(x)
val derivedFromY = derivedFromX * veryComplexComputation(y)
(x, derivedFromX, derivedFromY)
}
}
class Computed(x: Double, y: Double, z: Double) {
private def this(xyz: (Double, Double, Double)) =
this(xyz._1, xyz._2, xyz._3)
def this(x: Double, y: Double) =
this(Computed.computeArgs(x, y))
}
答案 1 :(得分:2)
我认为最好的方法是向配套对象添加合适的工厂方法:
object Computed {
def veryComplexComputation(x: Double) = math.sqrt(x) // can be private, if you wish
def apply(x: Double, y: Double): Computed = {
val derivedFromX = veryComplexComputation(x)
val derivedFromY = derivedFromX * veryComplexComputation(y)
new Computed(x, derivedFromX, derivedFromY)
}
}
然后你可以用与案例类相同的方式实例化你的Computed
类型,然后使用&#34; new&#34;:
scala> val comp = Computed(4.0, 9.0)
comp: Computed = Computed@4de4e24f
(您可能还想考虑将Computed
作为案例类 - 特别是如果完全或甚至大部分用作数据容器的话
答案 2 :(得分:0)
可以(ab)使用具有默认值的多个参数列表,如下所示:
class Computed(x: Double, y: Double, z: Double) {
def this(x: Double, y: Double) = {
this(
x,
Computed.veryComplexComputation(x),
Computed.veryComplexComputation(x) * Computed.veryComplexComputation(y)
)
}
}
这利用了每个参数列表可以访问先前列表中的参数的事实。只是不要忘记在调用构造函数时提供空参数列表:
class Computed(x: Double, y: Double, z: Double) {
def this(x: Double, y: Double)(
derivedFromX: Double = Computed.veryComplexComputation(x)
)(
derivedFromY: Double = derivedFromX * Computed.veryComplexComputation(y)
) = {
this(x, derivedFromX, derivedFromY)
}
}
答案 3 :(得分:0)
可以链接几个辅助构造函数,每个辅助构造函数执行一次计算,使用标记特征来区分构造函数,以避免模糊性过载。
object Computed {
def veryComplexComputation(x: Double) = math.sqrt(x) // imagine there is some much more complex computation here
private trait DerivedFromX
private object DerivedFromX extends DerivedFromX
}
class Computed(x: Double, y: Double, z: Double) {
private def this(name: Computed.DerivedFromX, x: Double, derivedFromX: Double, y: Double) = {
this(x, derivedFromX, derivedFromX * Computed.veryComplexComputation(y))
}
def this(x: Double, y: Double) = this(Computed.DerivedFromX, x, Computed.veryComplexComputation(x), y)
}