Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:两个相似的类,一个不可变的,它们之间共享代码_Java_Class_Immutability_Sharing - Fatal编程技术网

Java:两个相似的类,一个不可变的,它们之间共享代码

Java:两个相似的类,一个不可变的,它们之间共享代码,java,class,immutability,sharing,Java,Class,Immutability,Sharing,假设我有两门课。两者都有相同的成员字段(包括相同的名称),但一个类的成员字段声明为final(不可变),而另一个不是final。大多数成员方法都适用于这两个类 我如何与另一个类共享不可变类的成员方法(好像通过继承或其他方式),而不必将整个方法复制到另一个类中。我想没有这样的办法,但我想我应该先问一下。否则,我将在不同的名称空间中声明它们,并给它们相同的类名。应该注意的是,并非所有的不可变类方法都适用于可变类 public class ImmutableDoubleLine { publi

假设我有两门课。两者都有相同的成员字段(包括相同的名称),但一个类的成员字段声明为final(不可变),而另一个不是final。大多数成员方法都适用于这两个类

我如何与另一个类共享不可变类的成员方法(好像通过继承或其他方式),而不必将整个方法复制到另一个类中。我想没有这样的办法,但我想我应该先问一下。否则,我将在不同的名称空间中声明它们,并给它们相同的类名。应该注意的是,并非所有的不可变类方法都适用于可变类

public class ImmutableDoubleLine {
    public final DoublePoint origin;
    public final DoublePoint endPoint;

    // ...

    public double getLength() {
        return origin.calcDistance(endPoint);
    }
}

    public class MutableDoubleLine {
        public DoublePoint origin;
        public DoublePoint endPoint;

        // ...

// same code as immutable class
        public double getLength() {
            return origin.calcDistance(endPoint);
        }
    }

为什么要将字段声明为公共字段

只需将它们设置为私有,并仅在派生类中添加setter。不可变类没有setter,字段必须在构造函数中设置


通过这种方式,您不需要将DoublePoint设置为final,但要小心,如果您返回的是DoublePoint而不是final,则必须返回它们的防御性副本。

为什么要将字段声明为public

只需将它们设置为私有,并仅在派生类中添加setter。不可变类没有setter,字段必须在构造函数中设置


通过这种方式,您不需要将DoublePoint设置为最终版本,但要注意,如果您返回的是最终版本而不是最终版本,则必须首先返回它们的防御性副本。

这一点非常重要

除非类
DoublePoint
是内部不可变的,并且它的所有实例变量都是内部不可变的,使用
最终DoublePoint origin
语句所做的只是将引用设置为
origin
端点
,如果它们不能更改为指向不同的实例,则设置为
不可变doubleline
不可变

我之所以提到这一点,是因为您没有显示
DoublePoint
的代码

第二,针对您的实际问题,使用
接口
,并让两个类都实现它:

public interface DoubleLine
{
    public double getLength();
}

我会尽可能地使所有内容都不可变,这使调试更容易,并发性也更容易。

首先,这一点非常重要

除非类
DoublePoint
是内部不可变的,并且它的所有实例变量都是内部不可变的,使用
最终DoublePoint origin
语句所做的只是将引用设置为
origin
端点
,如果它们不能更改为指向不同的实例,则设置为
不可变doubleline
不可变

我之所以提到这一点,是因为您没有显示
DoublePoint
的代码

第二,针对您的实际问题,使用
接口
,并让两个类都实现它:

public interface DoubleLine
{
    public double getLength();
}

我会尽可能使所有内容都不可变,这会使调试更容易,并发性也更容易。

使用组合。让其中一个类保存另一个类的实例,并将成员方法传递给内部实例。这是一种门面类。

使用合成。让其中一个类保存另一个类的实例,并将成员方法传递给内部实例。这是一种facade类。

使它们都继承自抽象类
AbstractDoubleLine
,向该类添加两个抽象方法
getOrigin()
getEndPoint()
,并使用这些getter实现所有常用方法


不可变类的getter当然应该通过使DoublePoint实例不可变或通过防御复制来保证其不可变。

使它们都从抽象类继承
AbstractDoubleLine
,向该类添加两个抽象方法
getOrigin()
getEndPoint()
,并使用这些getter实现所有常用方法


不可变类的getter当然应该保证DoublePoint实例的不可变性,或者通过使它们不可变,或者通过防御性复制。

在不可变类中,使它们更容易公开。在可变类中,它们可能是私有的。不过,这个概念仍然是一样的。我仍然希望在它们之间共享代码,但只共享其中的一些方法。而且,在需要时不要忘记防御性复制。您需要做更多的工作来创建可变类中的getter(如果需要)和setter,但除此之外,所有代码都可以共享。@ratchetfreak是的,我正在编辑这方面的内容。我不确定他是否想直接返回对象,但如果他需要,他需要创建一个副本,否则另一个类可能会使用get请求您的DoublePoint,然后开始修改它们的状态。除非它们是不可变的,而它们很可能是不可变的。在这种情况下,防御副本是不必要的。在immutable类中,它将使它们更容易公开。在可变类中,它们可能是私有的。不过,这个概念仍然是一样的。我仍然希望在它们之间共享代码,但只共享其中的一些方法。而且,在需要时不要忘记防御性复制。您需要做更多的工作来创建可变类中的getter(如果需要)和setter,但除此之外,所有代码都可以共享。@ratchetfreak是的,我正在编辑这方面的内容。我不确定他是否想直接返回对象,但如果他需要,他需要创建一个副本,否则另一个类可能会使用get请求您的DoublePoint,然后开始修改它们的状态。除非它们是不可变的,而它们很可能是不可变的。在这种情况下,不需要防御副本。DoublePoint是不可变的。但这超出了问题的范围。在可变双线中,点可以是可变线