CodeGym /课程 /C# SELF /类和对象:创建、构造函数和初始化

类和对象:创建、构造函数和初始化

C# SELF
第 12 级 , 课程 0
可用

1. 创建对象

终于讲到对象的创建啦。其实你之前肯定见过,只不过这次我们详细聊聊。其实创建对象真的很简单。

要创建对象,你得用 new 操作符。一般来说,你会创建一个类的新实例(对象),然后直接把它赋值给同类型的变量。

类名 变量名 = new 类名(参数);
创建对象的语法

这里 类名 是对象的类型,变量名 是变量的名字(通常小写,比如 cat),= 右边就是创建这个类的新对象。

例子:

代码 说明
object o = new object();
创建一个 object 类型的对象
Cat pet = new Cat();
创建一个 Cat 类型的对象
var reader = new StreamReader("file.txt");
创建一个带参数的 StreamReader 对象

程序员经常会把变量名和类名写得一样,只不过变量名首字母小写。新手看到这种代码可能会有点懵:

代码
Student student = new Student();
Car car = new Car();
PersonInfo personInfo = new PersonInfo();

其实这种写法完全没问题——就是声明一个变量,然后直接用同类型的对象初始化。

左边是变量声明,右边是用 new 在内存里创建新对象。就这么简单!

2. 构造函数

你应该经常看到,创建对象的时候会传一些参数。有的对象要参数,有的又不用。这到底是怎么回事?

其实也很简单:每个类都有一个(或多个)专门用来处理创建对象时参数的方法。这种方法叫 构造函数。单个方法就叫 构造函数

构造函数和普通方法还是挺好区分的。它有两个特点:

  • 构造函数的名字和类名一样(而且首字母大写)
  • 构造函数没有返回值类型(连 void 都不写)。

一般长这样:


修饰符 类名(参数)
{
   构造函数代码
}
构造函数的语法

构造函数声明例子:

public class Point
{
    public int X;
    public int Y;

    public Point(int x, int y) // 构造函数
    {
        X = x;
        Y = y;
    }
}

用法:

Point p = new Point(5, 10); // 调用构造函数

new Point(5, 10) 创建对象时,会调用带两个参数的构造函数,初始化 XY 字段。

有时候构造函数的参数名和字段名一样——这样写方便。名字冲突时用 关键字 this 解决:

public Point(int x, int y)
{
    this.x = x; // this.x 是对象字段,x 是构造函数参数
    this.y = y;
}

3. 构造函数的调用

当你写 new 类名(参数) 时,C# 会:

  • 在内存里创建新对象,
  • 调用合适的构造函数,把你的参数传进去。

以猫类为例:

public class Cat
{
    public string Name;
    public int Age;

    public Cat(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

用法:

Cat cat = new Cat("瓦斯卡", 2); // 可以:会调用带两个参数的构造函数
Cat cat2 = new Cat("瓦斯卡");   // 不行:没有这种构造函数——编译报错
Cat cat3 = new Cat();           // 不行:没有无参数构造函数——编译报错

如果类只有带参数的构造函数,那你创建对象时必须给它传参数。

4. 多个构造函数

不过你也可以在类里写多个构造函数。构造函数数量和参数都不限。创建对象时,编译器会自动选参数最合适的那个构造函数。

例子:

public class Cat
{
    public const int UNKNOWN = -1;
    public string Name;
    public int Age;

    public Cat(string name, int age)
    {
        Name = name;
        Age = age;
    }

    public Cat(string name)
    {
        Name = name;
        Age = UNKNOWN; // 年龄未知时的默认值
    }
}

用法:

Cat cat1 = new Cat("瓦斯卡", 2); // 用第一个构造函数
Cat cat2 = new Cat("穆尔卡");     // 用第二个构造函数
Cat cat3 = new Cat();            // 报错!没有无参数构造函数

我们考虑到有时候猫的年龄可能不知道。为这种情况加了个常量 UNKNOWN,还有只带名字参数的构造函数。

注意我们在两个构造函数里都初始化了所有字段。缺的参数就用 UNKNOWN 常量补上。

5. 默认构造函数

如果你的类里一个构造函数都没写,编译器会自动加一个无参数的空构造函数:


public ClassName()
{
}
默认构造函数的语法

但如果你自己写了至少一个构造函数——默认的空构造函数就不会自动加了

例子1:

public class Cat
{
    public string Name;
    public int Age;
}

// 可以:
Cat cat = new Cat(); // 会调用默认的无参数构造函数

例子2:

public class Cat
{
    public string Name;
    public int Age;

    public Cat(string name) { Name = name; }
}

// 不可以:
Cat cat = new Cat(); // 报错:没有无参数构造函数了!

6. 变量初始化

在C#里,类变量可以在声明时直接初始化,也可以在构造函数里初始化。

例子:

public class Cat
{
    public string Name;
    public int Age = -1; // 初始值

    public Cat(string name, int age)
    {
        Name = name;
        Age = age; // 覆盖初始值
    }

    public Cat()
    {
        Name = "无名";
        // Age 还是 -1(初始值)
    }
}

说明:

  • new Cat("瓦斯卡", 2) 创建时,Age 先是 -1,然后构造函数把它改成 2
  • new Cat() 创建时,Age 还是 -1

7. 变量初始化顺序

新对象的数据初始化顺序如下:

  1. 类字段先拿到默认值(0 对于 intnull 对于引用类型等等)。
  2. 然后执行你在字段声明时写的初始化器,按代码里出现的顺序来。
  3. 最后才执行构造函数里的代码。

变量是在构造函数之前按声明顺序初始化的。所以字段之间有依赖关系时要小心。

错误例子

非静态字段不能用其他非静态变量初始化:


public class Solution
{
    public int a = 1; 
    public int b = a;        // 不能用 a
    public int c = a + b;   // 不能用 a 和 b
}
// 这种代码会编译报错!
错误:非静态字段初始化时不能互相引用

正确例子

对于静态变量 就没问题

public class Solution
{
    public static int a = 1;          // 明确设置 a = 1
    public static int b = a + 2;      // b = 1 + 2 ⇒ 3
    public static int c = a + b + 3;  // c = 1 + 3 + 3 ⇒ 7

    public Solution()
    {
        Console.WriteLine($"a = {a}, b = {b}, c = {c}");
        // 输出:a = 1, b = 3, c = 7 —— 就是你想要的
    }
}
静态字段初始化

正确例子2

静态字段甚至可以这样写:

public class Solution
{
    public static int a = b + c + 1;    // b 和 c 还都是 0
    public static int b = a + c + 2;    // a == 1, c 还是 0
    public static int c = a + b + 3;    // a == 1, b == 3
}
静态字段和它们的初始化顺序
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION