在Java中实现属性的优缺点

时间:2013-10-05 22:06:02

标签: c# java properties theory

在C#中存在一种称为Property的成员。这使您可以轻松简单地定义私有字段并提供简单或复杂的getter和setter,同时通过不必定义整个方法来节省空间。 Java没有这样的东西,从我所看到的,普遍的共识是吸收它并为私有变量定义完整的getter和setter方法。

目前,我一直在玩弄以下课程:

public class Property<T> {

    private T value = null;

    public Property(){}
    public Property(T initialValue){
        value = initialValue;
    }

    public T get(){
        return value;
    }

    public void set(T newValue){
        value = newValue;
    }

}

通过此实现,您可以定义仅需要getter和setter的简单属性: final Property<String> name = new Property<>("Dog");

或更高级的选项like the one that MSDN provides for C#:

...
public double seconds;

public final Property<Double> Hours = new Property<Double>(){
    @Override
    public Double get() {
        return seconds/3600;
    }

    @Override                                              
    public void set(Double newValue) {
        seconds = newValue * 3600;
    }
};
...

这个解决方案的优点和缺点是什么?

3 个答案:

答案 0 :(得分:2)

专业人士很明显。我会指出一些比C#更好的特性:

  1. 背衬区域隐藏起来,因此您不会意外地使用它而不是属性。 (但缺点是如果你愿意,你不能轻易选择使用支持字段)
  2. 与C#的自动属性不同,您可以选择仅覆盖getset方法,而不是两者,例如。

    public Property<List<String>> MyList = new Property<List<String>>(){
        @Override
        public List<String> get() {
            if (value == null)
                value = new ArrayList<String>();
            return value;
        }
        // set still works
    };
    
  3. 但是有缺点:

    1. 它不是Java语言或任何常见库的一部分,因此对于阅读代码的人(包括将来的自己)来说,这可能会让人感到困惑。
    2. 您无法更改getset方法的可见性:如果可以访问Property<T>,则可以获取并设置值。
    3. 如果您未创建Property字段final,则可以访问该字段的任何人都可以将其更改为自己的Property实施。这可能很有用,但主要是痛苦。
    4. (这是与C#属性共享的con)您无法更改传递给getset方法的参数。例如。您不能同时使用Property<MyType>set(MyType)方法set(CompatibleType)(除非您延长Property)。
    5. 普遍使用泛型意味着在运行时,(感谢type erasure)你普遍使用Object。如果您使用原语(例如,使用double vs Property<Double>),此装箱/拆箱可能会略微降低性能(在大多数应用中都不会引人注意)。
    6. 顺便说一下,Scala是一种在JVM上运行的语言,它包含属性作为本机功能,并与Java的属性版本(getter / setter)互操作。您可能想要研究一下,因为基本上其他人已经为您破解了Java语言。 =)

      总而言之,我会说你不应该试图让Java拥有属性。在罗马做到入乡随俗。如果你不喜欢罗马人的行为,那就沿着街道(斯卡拉)或全国各地(C#)行走。

答案 1 :(得分:1)

因此,对于名称,完整的语法现在将是:

theObject.name.set("new name");

关键是,你是如何访问该名称对象的?它是公共/受保护然后它可以被覆盖。它是私人的吗?那么你无论如何都不能在课外改变它。

您提出的解决方案只有在您已有权访问该对象时才有效,此时您不需要该解决方案。

答案 2 :(得分:0)

此解决方案的优点(您的匿名内部类)是,如果您不需要在其他任何地方实现此功能,它将使您免于为这种情况编写完整的额外类。

此解决方案的con 以后您可能希望在其他位置实现它,然后您需要重构代码以提取Property&lt; Double&gt;的实现。进入自己的班级以避免重复自己。

我会说,如果你很确定你不会在其他地方需要这个实现(我猜你不会),请继续使用后面的解决方案一个匿名的内部类。这是一个很好的。