我有些困惑为什么编程语言会有属性。我是一名Java程序员,在职业生涯的开始阶段,自从我真正开始理解它以来,Java就是我唯一编写的语言。
在Java中,当然没有属性,我们编写getThis()和setThat(...)方法。
如果有属性,我们会得到什么好处呢?
谢谢。
编辑:另一个问题:具有属性的语言中会出现什么命名约定?
我有些困惑为什么编程语言会有属性。我是一名Java程序员,在职业生涯的开始阶段,自从我真正开始理解它以来,Java就是我唯一编写的语言。
在Java中,当然没有属性,我们编写getThis()和setThat(...)方法。
如果有属性,我们会得到什么好处呢?
谢谢。
编辑:另一个问题:具有属性的语言中会出现什么命名约定?
// 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相同;没有必要重写绑定到数据成员的旧客户端代码。
button.Location += delta;
比:
button.setLocation(button.getLocation() + delta);
编辑:
以下代码假定您手动完成所有操作。在我的示例世界中,编译器将生成简单的get/set方法,并将所有直接变量访问转换为这些方法。如果这样做不行,则客户端代码必须重新编译,这违背了其重要目的。
原文:
属性的主要论点是它消除了从变量到方法的转换需要重新编译代码的需求。
例如:
public class Foo
{
public int 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,能够根据需要提供自己的set/get实现(但我不喜欢隐藏的方法调用)。
两个原因:
在Java中,getter和setter本质上是属性。
在其他现代语言(如c#)中,它只是使语法更易于使用/理解。
它们是不必要的,在大多数情况下都有解决方法。
这实际上是个人偏好问题,但如果您使用的语言支持它们,我建议使用它们 :)
一开始我也很苦恼,但现在我真的很欣赏它们。在我看来,属性允许我以自然的方式与公开数据交互,同时不失 getter/setter 方法提供的封装性。换句话说,我可以将我的属性视为字段,但如果选择不这样做,实际字段就不会被真正暴露出来。在 C# 3.0 中使用自动属性更好,因为对于大多数字段——我想要允许消费者读/写数据的字段——我需要编写的代码更少:
public string Prop { get; set; }
public string Prop { get; private set; }
一切关乎绑定
曾经我认为属性只是语法糖(即通过减少开发人员的输入量来帮助他们)。但随着我越来越多地进行GUI开发并开始使用绑定框架(JGoodies、JSR295),我发现,语言级别的属性远远不止是语法糖。
在绑定场景中,您基本上定义了规则,告诉系统“对象A的属性X应始终等于对象B的属性Y”。简写为:A.x <-> B.y
现在,想象一下您将如何在Java中编写绑定库。目前,无法直接引用 'x' 或 'y' 作为语言原语。你只能将它们作为字符串引用(并通过反射访问它们)。实际上,A."x" <-> B."y"
这在重构代码时会造成巨大的问题。
还有其他考虑因素,包括属性更改通知的正确实现。如果您查看我的代码,则每个setter都需要至少3行才能执行非常简单的操作。此外,其中的三行之一还包括另一个字符串:
public void setFoo(Foo foo){
Foo old = getFoo();
this.foo = foo;
changeSupport.firePropertyChange("foo", old, foo);
}
所有这些浮动的字符串都是一个完全的噩梦。
现在,想象一下如果属性是语言中的一等公民。这开始提供几乎无限的可能性(例如,想象一下直接向属性注册侦听器,而不必处理PropertyChangeSupport及其必须添加到每个类中的3个神秘方法)。想象一下能够将属性本身(而不是属性值,而是Property对象)传递到绑定框架中。
对于Web层开发人员,想象一下一个Web框架可以从属性名称自己构建表单ID值(类似于registerFormProperties(myObject.firstname, myObject.lastname, someOtherObject.amount)),以允许在将表单提交回服务器时进行对象属性值的往返填充。现在要做到这一点,您必须传递字符串,并且重构变得非常麻烦(一旦您依赖字符串和反射来连接事物,重构实际上变得非常可怕)。
所以,对于那些通过绑定处理动态数据更新的人来说,属性是语言中非常需要的功能 - 远远不止是语法糖。
您还可以创建派生字段和只读/只写字段。在我所使用的语言中,大多数属性不仅允许您分配简单字段,还允许您将完整函数分配给属性。