English 中文(简体)
Java:在采用静态方法时[封闭]
原标题:Java: When to make methods static v. instance [closed]
  • 时间:2009-10-24 20:20:04
  •  标签:
Closed. This question is opinion-based. It is not currently accepting answers.

我有一个<代码>基因类别,能够跟踪基因。 <代码>Gene有一个计算两种基因之间的距离的方法。 是否有任何理由使它静态?

哪些是更好的?

<代码>公开静态基因 Distance(Gene g0, Gene g1)

<代码>公开基因 Distance(Gene other)

Arguments f或/against making it static? I understand what it means f或 a member to be static, I m just interested in its implications f或 maximum cleanliness/efficiency/etc.

I repeat the same pattern f或 returning trimmed versions of two genes, finding matches between genes, finding matches between animals (which contain collections of genes), etc.

最佳回答

Instance, not static


我认为,对本案而言,第二项选择显然更好。 如果你认为,如果你愿意将物体传递给它,任何方法都可以作为静态执行,这只是一个特殊案例,因为其他参数也是一个例子。

因此,我们通过在两条试射器之间选择直截了当的操作员,对金属和抽象的探索稍有减弱。 但是,如果你看上<代码>.method>,则 然后,oper,这确实是一个问题。

此外,功能式链条的唯一途径是归属,即实例方法。 您可能希望<><>>___________________> ext.istance(x)/d> 工作。

问题回答

如果你采用静态的方法,就意味着可以在没有上下级的情况下使用这种方法。 这还意味着,除非通过提及物体,否则这种方法不能使用。

有时,采用固定方法是有道理的,因为这种方法与这一类别有关,但不是该类别的具体例子。 例如,所有教区方法,例如Integer.parse。 Int(String s。 将<代码>String改为int,但与<代码>的特定情况无关。 Integer Object.

另一方面,如果一种方法必须退还某些特定物体特有的数据(如大多数易碎和固定方法),那么这种数据便可能不会静止。

海事组织没有绝对的“优”一词,但<代码>公有基因(其他)在大纲上与 Java的其他方法(例如,目标等,可比较,比较)更为相似,因此我这样说。

我倾向于采用第二种方式,即出于以下原因采用实例方法:

  1. static methods make testing hard because they can t be replaced,
  2. static methods are more procedural oriented (and thus less object oriented).

海事组织的固定方法(如StingUtils)为通用类别(但我倾向于不使用这些类别)。

我对沙尔的回答说:

如果所涉方法打算以任何方式使用object的基本状态,则该方法便成为一种实例方法。 顺便说一句。

这取决于目标类别的设计方式。

在您的案例中,甲型六氯环己烷很可能是int gene Distance(Gene g0, Gene g1)does not 真正取决于Gene的状态。 我将把这种方法固定不变。 并将其归入“GeneUtils等公用事业类别。

当然,我不知道你的问题的其他方面,但这是我使用的一般规则。

P.S. -> 因此,我不会将这一方法放在Gene等舱内,因为一个基因不应负责计算其距离另一个基因的距离。

<代码>公开静态基因 Distance(Gene g0, Gene g1)将是一个单独的用途类别的一部分,例如CollectionsArrays in Java,而 公开基因 远距离(其他)将成为<代码>的一部分。 通用。 考虑到你们还有其他业务,如“两种基因的自然版本,在基因之间找到对应关系,在动物之间找到对应关系(包括基因收集),等等”,我将为它们单独设立固定用途类别,因为这些业务对于<>基因

如果可以将“遗传距离”的语词归纳为<条码>等值,那么你可以在那里消费,或者将其列入静态用途。

我首先要回答你提出的问题: 你们的阶级是谁的责任? 请允许我谈谈单一责任原则: 班级只能有改变的理由。 因此,我认为,如果你回答这个问题,你将能够决定如何设计你的申请。 在这种情况下,我既不使用第一种办法,也不使用第二种办法。 我认为,界定新的责任,将其归入单独类别或可能具有职能,是更好的。

我试图总结我同意的这里已经提出的一些问题。

我个人并不认为有一个“更好”的答案。 有效原因do存在于上,原因是你不放弃用固定方法填充的公用事业类别。

简短的回答是,在一个以目标为导向的世界里,你应当使用物体和与物体(资本、多变)相关的所有“货物”。

Polymorphism

如果计算基因距离的方法varies,请roughly。 (很可能是Strategy) 每个变式都有一个通用类别。 概述不同之处。 你们最后会有多个方面。

Open For Extension, Closed for Modification

这意味着,如果计算基因之间距离的新方法落下,请shouldn t 修改现有代码,但 添加新的。 你们冒着打破那里已经存在的东西的风险。

在这种情况下,你应当增加一个新的基因组,而不是修改在#geneDistance上写的代码。

Tell Don t Ask

你们应该告诉你们要做些什么,不要问他们自己的国家,并为他们作出决定。 http://en.wikipedia.org/wiki/Single_responsibility_principle” rel=“nofollow noretinger”>,single responsibility principle since that s poly吗?

Testability

静态方法可能很容易孤立地加以测试,但是,你将在其他班子使用这一固定方法。 在孤立地测试这些班级时,你将很难做。 或者不是。

页: 1 他的话比我能够说的话要好。

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));
    }    
}

这里有一只大塔和一个独木舟:调查Java SDK图书馆课堂的楼梯,看看你是否能够将不同班级固定方法的共体分类。

在这种情况下,我将把它当作一种隐蔽的方法。 如果你在0克无效时有合乎逻辑的答案,那么就必须使用BOTH(这种情况比你认为更经常发生)。

例如,aString.startsWith(, 如果法规无效,你可以认为,将合同归还无效(如果你认为职能可以是NUL-TOLERATE)。 这使我能够简化我的方案,因为没有必要在客户法典中进行点击。


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();
}

注:这是一个过于简化的例子。

只是一个想法。

我将采用这一榜样方法。 但这可能是因为我没有基因组别;)

实例方法可以被大大降低贵国法典复杂程度的子类所取代(无须作陈述)。 在静态方法中,会发生什么情况? 另一种静态方法? 如果你必须处理多变基因清单,那么你必须研究哪类基因来选择正确的距离方法......从而增加政变和复杂性。

我选择第二种办法。 在使这种方法静态化方面没有好处。 由于该方法属于基因组,因此静态只能增加一个没有额外收益的额外参数。 如果你需要一个实用的班子,那就是一种不同的交易。 但我认为,如果你能够把方法添加到有关类别,通常不需要使用类别。

我认为,问题领域应当超越一般性的大纲和(或)业务协调处的考虑。

例如,我猜测,就遗传分析而言,基因和距离的概念相当具体,不需要通过继承来专门处理。 如果情况并非如此,那么,人们可以提出选择例如方法的有力理由。

选择案件方法的主要原因是多变。 固定方法不能被子类所压倒,这意味着你可以根据具体情况具体实施。 这可能不适用于你,但值得一提。

如果基因距离完全独立于基因类型,我宁愿使用单独的通用类别,使这种独立性更加明确。 附有<条码>遗传学<>。 作为<代码>一部分的方法 通用类别意味着距离是一种与基因有关的行为。

我的回答非常有看法。

我将采取与<代码”相同的方式。 StringUtils.getLevenshteinDistance implementation in 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();
        }
    }

这样做的一些要点

  • There might be several distance implementations, so an utility method is more preferable than g0.distanceTo(g1)
  • I can static-import it for a short notation
  • I can test my implementation
  • 我还要补充:

    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 keyword is a hint for a JIT codificationer that the methods can be inlined. 我认为,你不需要重复处理这些事情,除非他们的手法几乎是瞬时的——少于微观秒,即一些扼杀行动或简单计算。 这可能是最近执行过程中Levenshtein距离完全静止的原因。

没有提到的两个重要考虑因素是基因1.geneDistance(gene2)是否总是与基因2.geneDistance(gene1)相匹配,以及基因是否和永远是密封的。 对于援引这些物品的类型而言,实例方法是多变的,而不是其论点的类型。 如果远距离功能被认为具有中转性,这可能会造成一些混乱,但不同类型的东西可能不同地计算距离。 如果远距离功能应具有中转性,并且被定义为两个班级都知道的最短转变,那么良好的模式可能是采用一种受保护的试样方法 int获得一个WayDistance(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;
}

这种设计将确保远程关系过境,同时允许个别类型报告其他类型可能不知道的情况。





相关问题
热门标签