OOP:使用属性和构造函数

本文关键字:构造函数 属性 OOP | 更新日期: 2023-09-27 18:06:27

我跟随c# complete reference。下面是演示Constructor and inheritance

的示例
class TwoDShape {
  double pri_width;
  double pri_height;
  // Properties for Width and Height.
  public double Width {
     get { return pri_width; }
     set { pri_width = value < 0 ? -value : value; }
  }
  public double Height {
     get { return pri_height; }
     set { pri_height = value < 0 ? -value : value; }
  }
class Triangle : TwoDShape {
  string Style;
  // Constructor.
  public Triangle(string s, double w, double h) {
    Width = w;   
    Height = h;  
    Style = s;   
  }

现在在Program.cs里面的Main()我有

static void Main() {
    Triangle t1 = new Triangle("isosceles", 4.0, 4.0);
    Triangle t2 = new Triangle("right", 8.0, 12.0);
}

我的问题是,当我们使用属性并可以使用它们初始化我们的字段时,为什么我们使用构造函数,然后在这个构造函数中初始化字段。

哪个是更好的方法使用构造/属性或这种方法。也请解释这种方法,因为我无法得到这个逻辑(构造函数和属性的初始化)

OOP:使用属性和构造函数

构造函数应该用于需要设置某些变量(属性)以使类处于正确状态的类。如果你只使用属性,不能保证这些属性被初始化,因为你不会得到编译错误,而且开发者很容易忘记初始化它们。

例如,假设您有一个在数据库中工作的类。如果你这样定义它:

public class UserRepository
{
    public DbConnection Connection { get; set; }
    public User GetUser(string id)
    {
        //...
    }
}

. .下面的代码可以很好地编译:

var repos = new UserRepository();
var user = repos.GetUser("22");

. .但是当你运行它时,你会得到一个异常。

如果你使用构造函数,你将无法使用类,除非你传递一个数据库连接。

public class UserRepository
{
    public UserRepository(DbConnection connection)
    {
        if (connection == null) throw new ArgumentNullException("connection");
        Connection = connection;
    }
    public DbConnection Connection { get; private set; }
    public User GetUser(string id)
    {
        //...
    }
}

//Now forced to init the class correctly
var repos = new UserRepository(dbConnection);
var user = repos.GetUser("22");

另一个方面是代码维护。最初编写代码时,通常可以完全控制代码所包含的内容以及如何初始化类。因此,一切都很顺利。但是当你几个月后回到这个项目时,你可能会忘记很多东西。如果你正在使用构造函数,那么你可以确保你创建的所有类都被正确初始化了。

简单来说,使用构造函数抽象了正在完成的工作,将其放在各种各样的黑盒中。

在属性上设置值给了用户更多的自由,但他们可能会做一些类的开发者没有预料到的事情。

这一切都归结为你愿意给那些使用你的类的人多少自由。

构造函数应该设置对象的所有必需字段。所以你应该实现一个构造函数来创建一个一致的实例。

创建实例后,您可以使用属性来更改对象状态,但这可能是危险的,因为这些更改可能导致实例的不正确状态。

我总是喜欢把我的类实现为不可变类型,所以你在构造函数中设置状态,只提供"getter"来访问字段的值。