我尝试谷歌搜索并搜索这个问题,但不知何故找不到任何相关的问题。我想知道是否有关于何时在类中使用属性的bbest-practice指南,何时不使用,而是使用单个方法的参数。
我很清楚很多情况,例如
public class Dog
{
private name;
public setName(...) {....}
}
但有时我不清楚使用什么更好。 例如。以下,使用:
public class calculation
XYZ bla;
public calculation(XYZ something)
{
this.bla = something;
}
public void calc1()
{
// some calculations with this.bla
}
public void calc1()
{
// some more calculations with this.bla
}
public XYZ getBla()
{
return this.bla;
}
}
或者可能:
public class calculation
public calculation() {}
public static XYZ calc1(XYZ bla) // maybe static, if not dependant on other attributes/instance-variables etc
{
// some calculations with bla
return bla;
}
public static XYZ calc1() // maybe static, if not dependant on other attributes/instance-variables etc
{
// some more calculations with bla
return bla;
}
}
我的意思是你可以争辩这两种情况。我看到两种不同风格的优点和缺点,但只要不需要太多参数/参数,我就更喜欢第二种风格。当然,如果我需要更多的属性等,那么第一个属性会更好,更简单等等,因为我不需要将这么多参数传递给方法......
只是个人风格的问题? 或者如何决定一种方法? 感谢
编辑:一个更好的例子:我正在进行大量的图像处理,并且问题是将图像内部存储在对象的状态或不存在。我目前没有这样做,因为我正在使用静态方法,并将图像自身I
压缩到每个方法:
public class ImageProcessing
{
/**
*
*/
public static Mat cannyEdges(Mat I, int low, int high)
{
// ...
return I;
}
public static Mat cannyEdges(Mat I)
{
return ImageProcessing.cannyEdges(I, ContourDetection.CANNY_LOWTHRES, ContourDetection.CANNY_HIGHTHRES);
}
/**
*
*/
public static Mat getHoughLines(Mat Edges, ...some_conf_vars...)
{
// ...
return I;
}
}
然后我就这样从外面打电话,例如:
// here: read image to I...
Mat edges = ImageProcessing.cannyEdges(I, 20, 100);
Mat lines = ImageProcessing.getHoughLines(I);
// draw lines...
问题是:I
是否属于对象的状态?转换为非静态然后使用例如:
// here: read image to I...
ImageProcessing IP = new ImageProcessing(I);
IP.cannyEdges(20, 100); // CHANGE OF cannyEdges: Also save `edges` internally as property!?
IP.calcHoughLines(); // also save the lines internally maybe?
Mat lines = IP.getLines();
// draw lines...
这更好吗?
然后出现的问题是:我应该在内部存储getHoughLines()
的结果(即lines
),还是应该直接将其返回给调用者?
答案 0 :(得分:2)
我可以使用一些例子:
public class Multiplier {
private int number;
public Multiplier(int number) {
this.number = number;
}
public int multiply(int other) {
return number * other;
}
}
此类可以实例化为:
Multiplier multiplyByTwo = new Multiplier(2);
我可以使用它将列表中的许多元素乘以2。
但我可能需要乘以数字对。所以下面的课程可能就是我所需要的:
public class Multiplier {
public static int multiply(int number, int other) {
return number * other;
}
}
我可以将它设为静态,因为不需要任何状态。
此示例可以在列表中使用:
for (int x:listOfInts) {
print(Multiplier.multiply(x * 2));
}
但可能在这个具体案例中,第一个例子更好。
for (int x:listOfInts) {
print(multiplyByTwo(x));
}
甚至更好地用于Java 8''''
如果我需要在代码中的许多点获取乘法元素和结果,我可以这样做。
class Multiplier {
private int x;
private int y;
public int multiply() {
return x * y;
}
// getters and setters for x and y
}
在最后一种情况下,我可能会考虑不添加setter并在构造函数中传递x,y。
每种结构都可以用于某些特定情况。
答案 1 :(得分:2)
这不完全是个人风格的问题。但是,我认为这个话题可能有点争议(基于意见),因此不适合Q / A网站。
然而,显而易见的问题是:相应类的对象是否真的带有状态?也就是说,实例所代表的状态是否有任何好处?如果实例的唯一目的是使用一系列set...
调用和最后调用execute()
方法修改的变量的累加器,那么通常没有真正的理由实例 - 除了避免使用带有“many”参数的静态方法。
我认为静态方法的优点超过了调用具有“许多”参数的方法的大多数潜在笨拙。其中一个最重要的可能是使用静态方法的方法不会增加状态空间。每个字段都是状态空间中的另一个维度,并且正确记录状态空间可能很难。静态方法强制执行更“功能”的编程风格:它们没有任何副作用,因此是线程安全的(这变得越来越重要)。
(注意:所有这些都是指不与任何静态状态相关的静态方法 - 无论如何都应该避免。当然,这是指方法,不涉及或针对与多态性相关的任何事情)。
毕竟,人们可以从任何地方轻松调用任何静态方法 - 甚至可以在实例方法中调用,并将某些字段作为参数传递。相反的情况并不那么容易:当你想调用一个依赖于许多实例字段的方法时,首先必须创建一个对象并适当地设置字段(仍然不知道它是否处于有效状态)可能会很麻烦调用方法)。我还看到Java 8的default
方法作为一个很好的应用案例,其中静态实用程序方法派上用场:default
方法可以轻松委托给实用程序方法,因为不涉及任何状态。
答案 2 :(得分:1)
何时不使用静电:
如果要返回的结果取决于构成你的"计算的其他变量(状态)"类然后静态不能使用。
但是,如果您只是对变量进行计算,如示例所示,静态可能是要采用的方式,因为它需要更少的代码(例如,通过第一种方法对变量执行calc1然后calc2)必须这样做:
calculation calc = new calculation(x)
calc.calc1();
calc.calc2();
XYZ y = calc.getBla();
虽然你可以做第二个例子
static import ...calculation.*;
...
XYZ y = calc2(calc1(x));
答案 3 :(得分:1)
我选择第一个选项有几个原因,即状态超过静态函数的对象,特别是对于复杂的计算,但也适用于更简单的计算。
至少这是我的2c。
你的第一个例子的奇怪部分是那些calcX
方法没有说明幂等性,所以不清楚当它被操纵时this.bla
是什么。对于具有可选设置的复杂计算,另一种方法是使用构建器模式构造不可变对象,然后提供基于固定对象状态和参数返回结果的calcX
方法。但这种适用性实际上取决于用例,所以YMMV。
更新:使用新代码,更多OOP方法是装饰Mat
。支持委托而不是继承,你会得到像
public class MyMat
{
private Mat i;
public MyMat(Mat i) {
this.i = i;
}
public Mat getBackingMat() {
return this.i;
}
public MyMat cannyEdges(int low, int high)
{
// ...
return new MyMat(I); // lets you chain operations
}
public MyMat cannyEdges()
{
return new MyMat(ImageProcessing.cannyEdges(I, ContourDetection.CANNY_LOWTHRES, ContourDetection.CANNY_HIGHTHRES));
}
public MyMat getHoughLines(...some_conf_vars...)
{
// ...
}
}
MyMat myMat = new MyMat(I);
lines = myMat.cannyEdges(20, 100).calcHoughLines();
这只是猜测,因为我不知道那些东西是什么意思。 :)