物业的动机是什么?

时间:2009-03-02 21:59:00

标签: java oop properties java-7

我有点困惑为什么语言有这些。我是一名Java程序员,在我的职业生涯开始时,Java是我写的唯一一种语言,因为我开始实际上,你知道,得到它。

所以在Java当然我们没有属性,我们编写了getThis()和setThat(...)方法。

拥有房产我们会获得什么?

感谢。

编辑:另一个问题:具有属性的语言中出现了哪些命名约定?

12 个答案:

答案 0 :(得分:9)

哪一个看起来更自然?

// A
person.setAge(25)
// B
person.age = 25;
// or
person.Age = 25; //depending on conventions, but that's beside the point

大多数人都会回答B.

这不仅是语法糖,它在做反射时也有帮助;实际上,您可以在不依赖方法名称的情况下区分数据和操作。

以下是C#中不熟悉属性的示例:

class Person
{
    public int Age
    {
        set
        {
            if(value<0)
                throw new ArgumentOutOfRangeException();

            OnChanged();
            age = value;
        }

        get { return age; }
    }

    private int age;
    protected virtual void OnChanged() { // ... }
}

此外,大多数人总是使用属性而不是稍后推广公共成员,原因与我们总是使用get / set相同;无需重写绑定到数据成员的旧客户端代码。

答案 1 :(得分:7)

语法更好:

button.Location += delta;

比:

button.setLocation(button.getLocation() + delta);

答案 2 :(得分:6)

编辑:

以下代码假定您手动完成所有操作。在我的示例世界中,编译器将生成简单的get / set方法并将所有直接变量访问转换为这些方法。如果没有,那么客户端代码将不得不重新编译,这将失去很大一部分目的。

原文:

属性的主要参数是,如果从变量转到方法,它就不需要重新编译代码。

例如:

public class Foo
{
    public int bar;
}

如果我们后来决定验证为“bar”,我们需要这样做:

public class Foo
{
    private int bar;

    public void setBar(final int val)
    {
        if(val <= 0)
        {
            throw new IllegalArgumentException("val must be > 0, was: " + val);
        }

        bar = val;
    }

    public int getBar()
    {
        return (bar);
    }
}

但添加set / get方法会破坏所有代码。如果它是通过属性完成的,那么您可以在事后添加验证,而不会破坏客户端代码。

我个人不喜欢这个想法 - 我对使用注释的想法感到非常高兴,并且可以根据需要自动设置/获取简单的set / get geterated(但是我没有喜欢隐藏方法调用。)

答案 3 :(得分:3)

有两个原因:

  1. Cleaned / terser语法;和
  2. 它更清楚地向类的用户表明状态(属性)和行为(方法)之间的区别。

答案 4 :(得分:2)

在Java中,getter和setter本质上是属性。

在其他现代语言(c#)等中,它只是使语法更容易使用/理解。

它们是不必要的,大多数情况下都有解决方法。

这真的是一个偏好问题,但如果您使用的语言支持它们,我建议使用它们:)

答案 5 :(得分:1)

我最初也在努力解决这个问题,但是我真的很欣赏他们。我看到它的方式,属性允许我以自然的方式与暴露的数据交互,而不会失去getter / setter方法提供的封装。换句话说,我可以将我的属性视为字段,但如果我不选择,则不会真正暴露实际字段。使用C#3.0中的自动属性,对于大多数字段来说它变得更好 - 我希望允许消费者读/写数据 - 我写的更少:

public string Prop { get; set; }

在我想要部分可见性的情况下,我可以轻松限制我想要的访问者。

public string Prop { get; private set; }

所有这一切都可以通过getter / setter方法完成,但是措词要高得多,而且使用率也不那么自然。

答案 6 :(得分:1)

面向对象编程的一般规则是您永远不会更改现有接口。这确保了在内部内容中可能会更改调用对象的对象,而不需要知道这一点。

其他语言的属性是伪装成特定语言特征的方法。在Java中,属性仅按惯例区分。虽然一般来说这是有效的,但有些情况会限制你。例如,有时您会使用hasSomething而不是isSomething of getSomething。

因此,它允许名称的灵活性,而工具和其他依赖的代码仍然可以区分。

此外,代码可以更紧凑,并且get和set按设计分组在一起。

答案 7 :(得分:1)

面向对象的软件构造2中 Bertrand Meyer称之为“统一访问原则”,一般的想法是当一个属性从一个简单的(即只是一个整数)变为派生的一个(函数调用),使用它的人不应该知道。

您不希望每个人都使用您的代码来改变

int x = foo.y;

int x = foo.y();

这打破了封装,因为你没有改变你的“界面”只是你的“实现”。

答案 8 :(得分:0)

您还可以创建派生字段和只读/只写字段。我在我所使用的语言中看到的大多数属性不仅允许您分配简单的字段,还可以为属性分配完整的函数。

答案 9 :(得分:0)

属性提供了一种简单的方法,可以将对象中一组逻辑背后的细节抽象为外部世界的单个值。

虽然您的属性可能仅作为一个值开始,但这种抽象将接口分离,以便稍后可以在影响最小的情况下更改其细节。

一般的经验法则是抽象和松耦合是好事。属性是实现两者的模式。

答案 10 :(得分:0)

语言级别的属性是个坏主意。对他们没有好的约定,他们隐藏了代码中的性能缺陷。

答案 11 :(得分:0)

关于绑定的全部内容

曾经有一段时间我认为属性只是语法糖(即通过让它们输入更少的东西来帮助开发人员)。随着我越来越多的GUI开发,并开始使用绑定框架(JGoodies,JSR295),我发现语言级属性远远超过语法糖。

在绑定方案中,您基本上定义了规则,即“对象A的属性X应始终等于对象B的属性Y”。简写是:A.x&lt; - &gt; B.y

现在,想象一下如何在Java中实际编写绑定库。现在,绝对不可能直接将'x'或'y'称为语言原语。您只能将它们称为字符串(并通过反射访问它们)。实质上,A。“x”&lt; - &gt; B. “Y”

当你去重构代码时,这会导致大量的大量问题。

还有其他注意事项,包括正确实施属性更改通知。如果你看一下我的代码,每个受祝福的setter都需要至少3行来做一些非常简单的事情。加上这3行中的一行包含另一个字符串:

public void setFoo(Foo foo){
  Foo old = getFoo();
  this.foo = foo;
  changeSupport.firePropertyChange("foo", old, foo);
}

所有这些浮动的字符串都是一场彻头彻尾的噩梦。

现在,想象一下房产是否是该语言的一等公民。这开始提供几乎无限的可能性(例如,想象一下直接用一个Property注册一个监听器而不必使用PropertyChangeSupport,并且它必须添加到每个类中的3个神秘方法)。想象一下,能够将属性本身(不是属性的值,而是Property对象)传递给绑定框架。

对于Web层开发人员,想象一个Web框架,可以从属性本身的名称构建自己的表单id值(类似于registerFormProperties(myObject.firstname,myObject.lastname,someOtherObject.amount)以允许往返当表单被提交回服务器时,对象属性值的数量。现在要做到这一点,你必须传入字符串,重构变得令人头疼(一旦你依赖字符串和反射,重构实际上变得非常可怕把事情搞砸了。)

无论如何,对于我们这些通过绑定处理动态数据更新的人来说,属性是语言中非常需要的功能 - 不仅仅是语法糖。