我应该公开类的属性吗?
Should I expose the properties of my classes?
在我所有的研究中,我了解到当我想让用户访问内部属性时,我不应该直接访问该属性,而是通过get/set方法来访问,例如:
class myClass
{
private int x;
public void SetX (int x)
{
this.x = x;
}
public int GetX ()
{
return this.x
}
}
因为它提供了额外的好处,允许程序员更容易地完全改变引擎而不影响用户,更容易调试,并为检查输入的有效性提供了更多的选项。
然而,自从我开始学习和编写c#以来,我注意到大多数"原生"语言的类都暴露了它们的属性,例如,设置/获取矩形(System.Drawing.Rectangle
)的位置或大小,您可以直接访问X
, Y
, Width
和Height
属性。
我认为暴露属性的唯一好处是代码更简单一些。公开属性还有其他好处吗?
什么时候应该公开属性,什么时候不应该?
你混淆了属性和字段。在c#中,属性可以像公共字段一样使用,但是在内部调用它们的get/set方法。例如,带有属性的类看起来像这样:
class MyClass
{
// Field, direct access to the internal representation
private int x;
// Property, access via methods, but syntax like field access
public int X {
get { return this.x; } // generates a get-method "int get_X()"
set { this.x = value; } // generates a set-method "void set_X(int value)"
}
}
当你现在像这样设置属性X: myClass.X = 42
时,编译器将其转换为 myClass.set_X(42)
,它调用在 set
块中声明的方法。类似字段的语法只是为了方便。
因此,您确实应该倾向于公开set/get-methods。只是在c#中,首选的方法是通过属性,它抽象了这些方法的实际调用,并允许您像使用字段一样使用它们。
基本上,你的问题是属性vs公共变量。什么时候用什么?
阅读这篇文章,包括评论。
整个讨论的快速总结:
- 反射在变量和属性上的工作方式不同,所以如果你依赖反射,
更容易使用所有属性。 - 你不能绑定一个变量。 将变量更改为属性是一个破坏性的更改。
暴露数据成员的琐碎属性实现是没有或很少有收益的大量代码,只有合理的原因可以:
-
提供对由于某种原因不能声明为const的成员变量的只读访问
-
如果你正在编写一个供第三方使用的组件,并且存在任何可能的组件必须被替换而不需要这些用户重新构建(将公共成员变量更改为属性会破坏接口,因此需要重新构建)。
同样,在属性中包装公共字段有两个原因——一个是你不能在不破坏二进制兼容性的情况下更改它。二是不能绑定字段。
Reflection code against fields looks very different from reflection code against
properties (FieldInfo vs. PropertyInfo for starters). So even if you can
recompile against the new binary, if you use reflection on that field
you're hosed.
在c#中,你使用属性而不是getter/setter方法,因为它们提供相同的功能。注意,fields != properties。参见MSDN: Properties.
就像您说的,不直接访问变量的好处是您可以更改实现而不需要对类的用户进行任何更改。在面向对象编程方面,我认为这是一件重要的事情。
另外,通过使用属性,您仍然可以影响"get"或"set"的工作。这在某些情况下是有用的
- 我应该使用什么来代替void作为变体中的替代类型之一
- boost::asio::steady_timer()与sleep()我应该使用哪一个
- 我应该实现右值推送功能吗?我应该使用std::move吗
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 我应该删除矢量<short>吗?
- 我应该如何修改此代码以使用给定字符串中的字母打印菱形图案
- 我应该在锁定TBitmap画布后解锁它吗
- 为什么我应该在异常处理中使用std::cerr而不是std::cout
- 我应该避免多重实现继承吗
- 为了方便起见,我应该避免公开私有字段变量吗
- 我收到同义重复编译器错误。我应该如何修复"类型"X"的参数与类型"X"的参数不兼容?
- 违反const正确性:我应该现实地期待什么问题
- 我应该如何表示我拥有的连续元素序列?
- 我应该将除 .cpp 以外的其他文件添加到 git 中吗?
- 我应该如何从 stdin C++ 中读取可变长度的格式字符串?
- 我有一个对象,它将在整个程序的持续时间内实例化,但一个类成员不会,我应该动态分配它吗?
- 我应该使用多个角色还是一个角色,将实际属性推迟到将数据包装/公开为其属性的QObject
- 如果某些实例不使用基类的属性,我应该继承子类吗?
- 我应该公开类的属性吗?
- 我应该如何存储和跟踪统一/属性位置