嵌套类是否可以用作纯数据集,类似于其他语言中的“Structs”?

huangapple go评论64阅读模式
英文:

Is it okay to use nested classes as pure data sets, kind of like other languages 'Structs'?

问题

正如标题所述,是否可以使用一个非常简单的嵌套类作为数据容器,类似于其他编程语言中存在的结构体(Struct)?

例如,想象一下,如果我需要一个方法返回多个值,是否可以使用这个非常简单的嵌套类来实现这个目的?或者这是一种不好的做法?

举个例子,想象一个场景,你需要使用绝对坐标(左、上、右、下)来绘制一个形状,并且想要获取屏幕上点击位置的 x 和 y 坐标,但是不是从这些坐标开始绘制形状,而是需要偏移它们以在这些坐标的中心绘制形状,就像下面的示例所示:

public class DrawSquare {
	
	private class Positions {
		public int left;
		public int top;
		public int right;
		public int bottom;
	}
	
	
	//* 这些类在 Java 中可能不存在。
	//* 它们只是用来说明功能。
	private Rectangle mSquare;
	private Paint mPaint;
	private Screen mScreen;
	
	private final int SIDE_LENGTH;
	
	public DrawSquare(int sideLength) {
		SIDE_LENGTH = sideLength;
		mSquare = new Rectangle();
	}
	
	//* 在屏幕点击的位置创建一个正方形。
	public void createSquare() {
		Positions pos = processCoords(
				mScreen.getClickedX(),
				mScreen.getClickedY());
				
		//* 由于坐标已经被处理,这个矩形
		//* 将在点击坐标的中心创建。
		mSquare.set(pos.left, pos.top, pos.right, pos.bottom);
		mPaint.draw(mSquare, mScreen);
	}
	
	
	//* 移动正方形
	public void moveSquare() {
		Positions pos = processCoords(
				mScreen.getClickedX(),
				mScreen.getClickedY());
				
		//* 由于坐标已经被处理,这个矩形
		//* 将被移动到点击坐标的中心。
		mPaint.animate(mSquare, mScreen)
				.moveTo(pos.left, pos.top, pos.right, pos.bottom)
				.setDuration(500)
				.start();
	}
	
	//* 将坐标偏移以获得一个居中的正方形
	private Positions processCoords(int x, int y) {
		Positions pos = new Positions();
		int halfLength = SIDE_LENGTH / 2;
		
		pos.left = x - halfLength;
		pos.top = y - halfLength;
		pos.right = x + halfLength;
		pos.bottom = y + halfLength;
		
		return pos;
	}
	
}

上述示例中的对象类型只是虚构的,用于说明上述情景。

这是嵌套类的一个好的使用案例吗?

英文:

As the title says, is it okay to use a very trivial nested class just as a data holder, to act like a Struct existent in other programming languages?

For example, imagine that I need a method to return more than one value, is it okay to use this very simple nested class for this purpose? Or is it a bad practice?

As an example, imagine a scenario where you have to draw a shape using absolute coordinates (left, top, right, bottom) and what to retrieve the x and y coordinates clicked on a screen, but instead of starting to draw the shape at those coordinates, we need to offset them to draw the shape in the center of those coords, like this example demonstrate:


public class DrawSquare {
	
	private class Positions {
		public int left;
		public int top;
		public int right;
		public int bottom;
	}
	
	
	//* These classes may not exist in java.
	//* They're here just to exemplify functionality.
	private Rectangle mSquare;
	private Paint mPaint;
	private Screen mScreen;
	
	private final int SIDE_LENGTH;
	
	public DrawSquare(int sideLength) {
		SIDE_LENGTH = sideLength;
		mSquare = new Rectangle();
	}
	
	//* Creates a square where the screen was clicked.
	public void createSquare() {
		Positions pos = processCoords(
				mScreen.getClickedX(),
				mScreen.getClickedY());
				
		//* Because the coords were processed, this rectangle
		//* will be created in the center of the clicked coords.
		mSquare.set(pos.left, pos.top, pos.right, pos.bottom);
		mPaint.draw(mSquare, mScreen);
	}
	
	
	//* Moves the square
	public void moveSquare() {
		Positions pos = processCoords(
				mScreen.getClickedX(),
				mScreen.getClickedY());
				
		//* Because the coords were processed, this rectangle
		//* will be moved to the center of the clicked coords.
		mPaint.animate(mSquare, mScreen)
				.moveTo(pos.left, pos.top, pos.right, pos.bottom)
				.setDuration(500)
				.start();
	}
	
	//* offset the coords to get a centered square
	private Positions processCoords(int x, int y) {
		Positions pos = new Positions();
		int halfLength = SIDE_LENGTH / 2;
		
		pos.left = x - halfLength;
		pos.top = y - halfLength;
		pos.right = x + halfLength;
		pos.bottom = y + halfLength;
		
		return pos;
	}
	
}

Those are just made up object types to exemplify the scenario I stated above.

Is that a good use case of a nested class?

答案1

得分: 1

这种方法几乎是不错的,只有一个小问题:

使用静态嵌套类而不是内部类:

public class DrawSquare {

    private static class Positions {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }

区别在于,静态嵌套类不需要对 DrawSquare 的引用。


在 Java 14 中,记录是一个预览功能。
其中之一就是你正在进行的操作:

public class DrawSquare {

    private record Positions(int left, int top, int right, int bottom) {}

记录是不可变的,因此你需要稍微修改你的创建方式:

private Positions processCoords(int x, int y) {
    int halfLength = SIDE_LENGTH / 2;

    int left = x - halfLength;
    int top = y - halfLength;
    int right = x + halfLength;
    int bottom = y + halfLength;

    return new Positions(left, top, right, bottom);
}

记录将自动为您创建构造函数、访问器(.left()...)以及重载的 .equals(Object other).hashCode().toString()

但在此功能成为标准 Java(不再是预览版)之前,您的方法是可以的。

英文:

That approach is almost fine, with a small nitpick:

Use a static nested class instead of an inner class:

public class DrawSquare {
private static class Positions {
public int left;
public int top;
public int right;
public int bottom;
}

The difference is that a static nested class does not need a reference to a DrawSquare.


In Java 14, records are a preview feature.
One of the uses for them are exactly what you are doing there:

public class DrawSquare {
private record Positions(int left, int top, int right, int bottom) {}

Records are immutable, so you would have to change your creation a bit:

private Positions processCoords(int x, int y) {
int halfLength = SIDE_LENGTH / 2;
int left = x - halfLength;
int top = y - halfLength;
int right = x + halfLength;
int bottom = y + halfLength;
return new Positions(left, top, right, bottom);
}

A record will automatically create a constructor, accessors (.left()...) and overload .equals(Object other), .hashCode() and .toString() for you.

But until this feature is in standard Java (without preview), your approach is fine.

huangapple
  • 本文由 发表于 2020年4月9日 23:04:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/61124240.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定