我有一个Gene
,用于跟踪基因的类。 Gene
具有用于计算两个基因之间的距离的方法。 是否有任何理由使其静态的?
哪个更好?
public static int geneDistance(Gene g0, Gene g1)
要么
public int geneDistance(Gene other)
参数/反对使其静态的? 我明白它的意思为成员是静态的,我在其最大的清洁/效率/等影响刚刚兴趣。
我重复同样的模式返回两个基因的修剪的版本,寻找基因之间的匹配,寻找动物之间的比赛(包含基因的集合),等等。
Answer 1:
例如,不是静态的
对于这种情况,我认为第二个选择显然是更好的。 如果你想想看,任何方法可以为静态的,如果你愿意的对象传递给它的实施,这只是似乎是一个特例,因为其他参数也是一个实例。
因此,我们的对称性和抽象搜索通过具有用于点操作两个实例对象之间进行选择轻微冒犯。 但是,如果你看一下.method
为.
那么运营商来说,是不是一个真正的问题。
另外,做函数式链接的唯一方法是使用一个属性,即实例方法。 你可能想thing.up.down.parent.next.distance(x)
工作。
Answer 2:
当你的方法静态的,这意味着该方法可以在不类的实例调用。 这也意味着,除非它被传递给一个对象的引用的方法不能访问实例变量。
有时,它是有道理的制作方法静态的,因为该方法与类相关联,但不是类的特定实例。 例如,所有的parseX方法,如Integer.parseInt(String s
)。 这是一个转换String
到int
,但没有任何与一个特定实例Integer
对象。
如果,在另一方面,一种方法必须返回一些数据是唯一的一个对象的特定实例,(最喜欢的获取和设置方法),那么就不能是静态的。
Answer 3:
IMO也没有绝对的“好”,但public int geneDistance(Gene other)
的曲风更类似于Java的其他方法(如的Object.Equals,Comparable.compareTo),所以我会走那条路。
Answer 4:
我倾向于第二种形式,由于以下原因,即实例方法:
- 静态方法使测试很难,因为它们无法替代的,
- 静态方法更程序取向(以及因此更小的面向对象)。
IMO,静态方法是OK的实用工具类(如StringUtils的),但我更喜欢使用它们不能滥用。
Answer 5:
我查理的回答措词:
如果有问题的方法拟使用底层对象的状态以任何方式,使其成为一个实例方法。 否则,使其静态的。
这依赖于对象的类的设计方式。
在你的情况,alphazero,可能是 并不真正依赖于例如,它被称为上的状态。 我会做这个方法是静态的。 并把它放在一个工具类像
当然,也有可能是你的问题的其他方面,我不知道,但这是规则的一般经验,我使用。
PS - >我不会把该方法在类本身的原因是因为一个基因不应该是负责从另一个基因计算它的距离。 ;-)
Answer 6:
public static int geneDistance(Gene g0, Gene g1)
将是一个单独的工具类等的一部分的Collections
和Arrays
在Java中,而public int geneDistance(Gene other)
将是部分Gene
类。 考虑到你有一个像其他业务“两个基因的修剪的版本,寻找基因之间的匹配,寻找动物之间的比赛(包含基因的集合),等等”我会创建一个单独的静态实用工具类他们作为这些操作不是语义上有意义到什么Gene
是。
如果“基因距离”的语义可以被包装成你equals(Object o)
方法,那么你可以有食用它,否则它包含在你的静态工具。
Answer 7:
我想开始回答在新一个你的问题:你的类基因是什么负责? 可能你已经听说过关于“单一职责原则”:A类应该只有一个理由去改变。 所以,如果你回答这个问题,你就可以决定如何您的应用程序应设计,我相信。 在这种特殊情况下,我不会使用既不是第一次的做法,也不第二个。 在我看来,这是好多了定义新的责任,并在一个单独的类封装,或可能是一个功能。
Answer 8:
我会试着总结了一些对我同意这个已经给出的点。
我个人不认为这是一个“感觉更好”的答案。 正当的理由做你为什么不wan't充满了静态方法的实用程序类存在 。
简短的回答是,在面向对象的世界里,你应该使用对象和所有的好“东西”随他们(封装,多态)
多态性
如果计算基因之间的距离的方法各不相同 ,你应该大致 (更可能是一个战略 )有每变化的基因类。 封装什么变化。 否则,你最终会与多个IFS。
对扩展开放,对修改关闭
这意味着,如果计算基因之间的距离的新方法出现向下行,你不应该修改现有的代码 ,而是添加新的 。 否则,你可能打破什么是已经存在。
在这种情况下,你应该添加一个新的基因类,不能修改写在#geneDistance代码
告诉不问
你应该告诉你的对象做什么,不问他们的状态,并为他们做决定。 突然,你打破了单一职责princi PLE因为这是多态。
可测性
静态方法可能很容易在隔离测试,但在路上,你会利用在其他类此静态方法。 当涉及到测试上隔离类,你将很难做。 或者说不是。
我会让MISKO有他的说法是更有可能比能来我提出更好。
import junit.framework.Assert;
import org.junit.Test;
public class GeneTest
{
public static abstract class Gene
{
public abstract int geneDistance(Gene other);
}
public static class GeneUtils
{
public static int geneDistance(Gene g0, Gene g1)
{
if( g0.equals(polymorphicGene) )
return g0.geneDistance(g1);
else if( g0.equals(oneDistanceGene) )
return 1;
else if( g0.equals(dummyGene) )
return -1;
else
return 0;
}
}
private static Gene polymorphicGene = new Gene()
{
@Override
public int geneDistance(Gene other) {
return other.geneDistance(other);
}
};
private static Gene zeroDistanceGene = new Gene()
{
@Override
public int geneDistance(Gene other) {
return 0;
}
};
private static Gene oneDistanceGene = new Gene()
{
@Override
public int geneDistance(Gene other) {
return 1;
}
};
private static Gene hardToTestOnIsolationGene = new Gene()
{
@Override
public int geneDistance(Gene other) {
return GeneUtils.geneDistance(this, other);
}
};
private static Gene dummyGene = new Gene()
{
@Override
public int geneDistance(Gene other) {
return -1;
}
};
@Test
public void testPolymorphism()
{
Assert.assertEquals(0, polymorphicGene.geneDistance(zeroDistanceGene));
Assert.assertEquals(1, polymorphicGene.geneDistance(oneDistanceGene));
Assert.assertEquals(-1, polymorphicGene.geneDistance(dummyGene));
}
@Test
public void testTestability()
{
Assert.assertEquals(0, hardToTestOnIsolationGene.geneDistance(dummyGene));
Assert.assertEquals(-1, polymorphicGene.geneDistance(dummyGene));
}
@Test
public void testOpenForExtensionClosedForModification()
{
Assert.assertEquals(0, GeneUtils.geneDistance(polymorphicGene, zeroDistanceGene));
Assert.assertEquals(1, GeneUtils.geneDistance(oneDistanceGene, null));
Assert.assertEquals(-1, GeneUtils.geneDistance(dummyGene, null));
}
}
Answer 9:
这里有一个元的答案,和一个有趣的练习:调查一堆Java SDK中的库类的,看看你是否可以归类在不同类的静态方法之间的共性。
Answer 10:
在这种特殊情况下,我会让它的intance方法。 但如果你有一个合乎逻辑的答案时,G0为null,则同时使用(这比你想象的更经常发生)。
例如, aString.startsWith()
如果ASTRING为空,你可能会认为这是合乎逻辑的返回null(如果你认为该函数可以为NULL,容忍)。 这让我简化我的程序一点,因为没有必要有ASTRING检查空在客户端代码。
final Stirng aPrefix = "-";
final Vector aStrings = new Vector();
for(final String aString : aStrings) {
if (MyString.startsWith(aString, aPrefix))
aStrings.aStringadd();
}
代替
final Stirng aPrefix = "-";
final Vector aStrings = new Vector();
for(final String aString : aStrings) {
if ((aString != null) && aString.startsWith(aPrefix))
aStrings.aStringadd();
}
注意:这是一个过于简化的示例。
只是一个想法。
Answer 11:
我会做这样的一个实例方法。 但是,这可能是由于这样的事实,我没有基因的线索;)
实例方法可以由子类大大降低了代码的复杂性(不太需要if语句)覆盖。 在静态方法例如,会发生什么我你得到它的距离的计算方法不同基因的特定类型的? 广告另一个静态方法? 如果你不得不处理的基因多态列表中,您不得不看基因的类型来选择正确的距离法......这增加了连接和复杂性。
Answer 12:
我选择了第二种方法。 我看到在使静态方法没有任何优势。 由于该方法是在基因类,使其静态只会增加,没有额外的增益一个额外的参数。 如果你需要一个实用程序类,这是一个完全不同的交易。 但在我看来有通常不需要一个实用程序类,如果你能在问题的方法添加到类。
Answer 13:
我觉得这个问题应该域告知答案超出了一般的风格和/或OO考虑。
例如,我猜,进行基因分析的领域,“基因”和“距离”的概念是相当具体的,通过继承不需要专业化。 是不是这么回事,我们可以做一个强大的情况下选择了实例方法。
Answer 14:
喜欢的实例方法的主要原因是多态。 静态方法不能被一个子类,这意味着你不能自定义基于实例类型的实现覆盖。 这可能不是你的情况适用,但它是值得一提。
如果基因距离是完全独立于基因的类型,我宁愿使用一个单独的实用工具类,使这种独立性更加明确。 有一个geneDistance
方法的一部分Gene
类意味着距离是与基因实例的行为。
Answer 15:
我的回答是很固执己见。
我会去以同样的方式为一体的StringUtils.getLevenshteinDistance
在StringUtils的实现。
public interface GeneDistance{
public int get();
}
public class GeneDistanceImpl implements GeneDistance{
public int get(){ ... }
}
public class GeneUtils{
public static int geneDistance(Gene g0, Gene g1){
return new GeneDistanceImpl(g0, g1).get();
}
}
对于做这种方式的几点
- 可能有几个距离实现,所以一个实用方法比更优选
g0.distanceTo(g1)
- 我可以静态导入它的短符号
- 我可以测试我的实现
我还可以补充一点:
class Gene{ // ... Gene implementation ... public int distanceTo(Gene other){ return distance.get(this, GeneUtils.getDefaultDistanceImpl()); } public int distanceTo(Gene other, GeneDistance distance){ return distance.get(this, other); } }
其中一个原因,使一个复杂的方法完全是静态的表现。 static
关键字为JIT编译器,该方法可以被内联的提示。 在我看来,你他/她不需要理会这些事情,除非他们的方法调用几乎是瞬间完成 - 不到一微秒,即一些字符串操作或一个简单的计算。 这可能是为什么Levenshtein距离在最新的执行工作取得完全静态的原因。
Answer 16:
其中没有提到两个重要的考虑因素是是否gene1.geneDistance(基因2)总是预期相符gene2.geneDistance(基因1),以及是否基因是而且将永远是一个密封类。 实例方法是多态的相对于该类型在调用它们的东西,而不是类型的他们的论据。 这可能会导致一些混乱,如果距离函数应该是传递的,但不同类型的东西可能会计算距离不同。 如果距离函数应该是传递的,并且被定义为,要么类知道最短的改造,一个良好的模式可能有一个受保护的实例方法int getOneWayDistance(Gene other)
,然后碰到这样的:
public static int geneDistance(Gene g0, Gene g1)
{
int d0=g0.getOneWayDistance(g1);
int d1=g1.getOneWayDistance(g0);
if (d0 < d1) return d0; else return d1;
}
这样的设计将保证距离关系的行为传递性,同时允许个别类型的报告的快捷方式到其他类型的那些其他类型可能不知道的情况下。
文章来源: Java: When to make methods static v. instance [closed]