面向对象编程中的 字段 vs 属性

在面向对象编程中,字段(field)和属性(property)是表示对象内部数据的两种不同方式。尽管两者都用于存储数据,但属性提供了额外的功能,允许控制如何访问和修改数据。


字段是一个变量,用于在对象中存储值。它是一个简单的数据结构,可以直接由代码访问和修改。字段通常在类定义的开始处声明,可以具有不同的访问修饰符,例如public,private或protected。

属性是字段和一组方法的组合,用于访问该字段。属性用于控制对象中的数据如何被访问或修改。它们可以提供验证、错误检查或甚至动态计算值。属性具有一个get方法(getter)来检索字段的值和一个set方法(setter)来修改它。

在一些编程语言中,例如C#,可以使用简写语法来定义属性,这看起来类似于字段声明,但是增加了get或set关键字:

public class Person
{
    private string name; // Field declaration

    public string Name // Property declaration
    {
        get { return name; } // Get accessor for the name field
        set { name = value; } // Set accessor for the name field
    }
}

在这个例子中,name字段是一个私有的成员变量,他存储了person的名字(字符串形式);而Name则作为属性,负责控制对name字段的访问。get方法返回了name字段的值,而set方法可以去修改它。

当然C#里还有另一种写法,编译器会负责自动生成默认的gettersetter

public class Person {
    public string Name { get; set; }
}

而c++中并没有这样的关键字,其写法更为的“传统”:

#include <iostream>
#include <string>
using namespace std;

class Person {
private:
    string name; // field declaration

public:
    string get_name() const { // property get accessor method
        return name;
    }

    void set_name(const string& new_name) { // property set accessor method
        name = new_name;
    }
};

int main() {
    Person p;
    p.set_name("John Doe");
    cout << "Name: " << p.get_name() << endl;
    return 0;
}

在这个例子中,我们有一个 Person 类,它有一个私有字段 name,它是一个存储人名的 std::string 对象。与人交流的时候,还可以说该类还有一个名为 name 的公共属性,它有一个获取访问器方法 get_name() 和一个设置访问器方法 set_name()get_name() 方法返回字段的值,set_name() 方法将字段的值设置为作为参数传入的值。 在 main() 函数中,我们创建了一个 Person 对象 p,使用 set_name() 方法将其名称设置为“John Doe”,然后使用 get_name() 方法输出名称。

要确定类的成员是字段还是属性,就是检查它是否具有gettersetter方法。如果一个成员既有getter方法又有setter方法,则很可能是属性。如果它只有一个字段声明,则只是一个单纯的字段。


为什么要有字段,还要有属性?

字段面向的使用情形:

  • 需要一种简单的方法来存储和访问数据,而不需要任何额外的逻辑或验证。
  • 成员字段根本无需向外部公开,即它只用于类内的数据处理。
  • 需要存储大量数据而不需要任何额外的功能。

使用属性时:

  • 需要控制对存储在字段中的数据的访问。
  • 当获取或设置数据时,希望添加附加逻辑或验证。
  • 需要根据对象中存储的其他数据提供计算值。
  • 希望在派生类中覆盖属性以提供多态行为。
  • 希望以安全和受控的方式向其他类公开存储在字段中的数据。

总的来说,使用字段或属性的决策取决于程序的具体要求。如果您需要超出简单数据存储和检索之外的其他功能,则属性可能是更好的选择。但是,如果您只需要存储和访问数据而没有任何额外的逻辑或验证,则字段可能更合适。

class Person {
private:
    std::string name; // field

public:
    void setName(const std::string& newName) {
        name = newName; // direct access to field
    }
};

在这个例子中,我们有一个 Person 类,它有一个名为 name 的私有字段。 setName 函数直接访问字段来设置它的值。这是一个简单的案例,我们只需要存储和访问数据而无需任何额外的逻辑或验证。

class Rectangle {
private:
    int width; // field
    int height; // field

public:
    int getWidth() const {
        return width;
    }

    void setWidth(int newWidth) {
        if (newWidth > 0) {
            width = newWidth; // additional validation
        }
    }

    int getHeight() const {
        return height;
    }

    void setHeight(int newHeight) {
        if (newHeight > 0) {
            height = newHeight; // additional validation
        }
    }

    int getArea() const {
        return width * height; // computed value based on other data
    }
};

在此示例中,我们有一个 Rectangle 类,其中包含宽度width和高度height的私有字段。我们提供公共属性来控制访问并添加额外的逻辑和验证,而不是直接访问这些字段。 setWidthsetHeight 函数在设置相应字段之前验证新值是否为正。 getArea 函数根据宽度和高度字段计算矩形的面积。


总结来说,字段和属性是在面向对象程序中表示数据的两种不同方式。虽然字段是简单的变量,用于存储数据,但属性提供了对该数据的控制访问,并可以提供额外的功能。了解字段和属性之间的差异对于创建高效和有效的面向对象代码至关重要。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Claude的羽毛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值