7.2 C#的类全解(概念、声明、成员、修饰符、重载)


7.2.1 类的概念

类(Class)是面向对象编程(OOP)中的核心概念之一,它作为创建对象的模板或蓝图,定义了对象的属性(数据)和方法(行为)。以下是类的一些关键特性和组成:

类的关键特性

  1. 抽象:类是对现实世界中事物的抽象,它定义了事物的通用特征和行为。

  2. 封装:类将数据和操作这些数据的方法组合在一起,并隐藏内部的实现细节,只对外提供有限的接口。

  3. 继承:类可以通过继承机制复用代码,子类可以继承父类的属性和方法。

  4. 多态:类可以实现多态性,即同一个方法在不同的对象中可以有不同的实现。

类的组成

  1. 数据成员

    • 常量:在类中不会被修改的变量。
    • (Field):类中用于存储数据的变量。
  2. 函数成员

    • 方法(Method):类中定义的函数,用于执行类的行为。
    • 属性(Property):用于控制对类中字段的访问。
    • 事件(Event):用于处理对象间的通信。
    • 索引器(Indexer):允许对象被索引,就像数组一样。
    • 运算符(Operator):允许对类类型使用标准的C#运算符。
    • 构造函数:用于初始化新创建的对象。
      • 实例构造函数:初始化非静态成员。
      • 静态构造函数:初始化静态成员。
    • 析构函数(Destructor):在对象被销毁前执行清理工作。
  3. 嵌套类型:类中可以定义的其他类或结构。

示例代码

以下是C#中定义一个简单的类的例子:

using System;

// 定义一个类
public class Person
{
    // 数据成员
    private string name;
    public int Age { get; set; }
    
    // 函数成员
    public void Eat()
    {
        Console.WriteLine("Eating");
    }
    
    public void Sleep()
    {
        Console.WriteLine("Sleeping");
    }
    
    // 构造函数
    public Person(string name)
    {
        this.name = name;
    }
    
    // 静态构造函数
    static Person()
    {
        Console.WriteLine("Static constructor executed.");
    }
    
    // 嵌套类型
    public class InnerClass
    {
        public void Display()
        {
            Console.WriteLine("Inner class method.");
        }
    }
}

public class Program
{
    public static void Main()
    {
        // 创建Person类的实例
        Person person = new Person("Alice");
        person.Eat();
        person.Sleep();
        
        // 创建嵌套类的实例
        Person.InnerClass innerClass = new Person.InnerClass();
        innerClass.Display();
    }
}

在这个示例中,Person类有两个数据成员(nameAge),两个方法(EatSleep),一个构造函数,一个静态构造函数和一个嵌套类型(InnerClass)。Main方法展示了如何创建Person对象和InnerClass对象的实例。

类是面向对象编程中实现封装和抽象的基础,是构建软件时组织代码的逻辑单元。

7.2.2 类的声明

在C#中,可以通过类修饰符来控制类的可见性和可访问性。以下是一些常用的类修饰符:

  1. public

    • 描述:类可以被任何其他类访问。
    • 例如:public class Car { ... }
  2. private

    • 描述:类只能在定义它的程序集中访问。
    • 例如:private class Car { ... }(不常用,因为通常嵌套类使用private)
  3. internal

    • 描述:类只在当前程序集中可访问。
    • 例如:internal class Car { ... }
  4. protected

    • 描述:类可以被定义它的类以及其派生类访问(不常用于类本身,常用于成员)。
    • 例如:protected class Car { ... }(不常用,因为通常继承中使用protected)
  5. static

    • 描述:类不能实例化,所有成员都是静态的。
    • 例如:static class Car { ... }
  6. sealed

    • 描述:类不能被继承。
    • 例如:public sealed class Car { ... }
  7. abstract

    • 描述:类不能被实例化,它可能包含未实现的方法(抽象方法),这些方法必须在派生类中实现。
    • 例如:public abstract class Car { ... }
  8. partial

    • 描述:类的定义被拆分到多个代码文件中,这在大型项目中很常见。
    • 例如:public partial class Car { ... }

示例代码:定义汽车类

以下是定义一个简单的汽车类的例子:

public class Car
{
    public string Color { get; set; }
    public string Brand { get; set; }
    public int Year { get; set; }

    public Car(string brand, string color, int year)
    {
        Brand = brand;
        Color = color;
        Year = year;
    }

    public void StartEngine()
    {
        Console.WriteLine("Engine started!");
    }
}

在这个示例中,Car类被声明为public,这意味着它可以在任何地方被访问。它有3个自动实现的属性:ColorBrandYear,以及一个方法StartEngine

继承方式

在C#中,当一个类继承自另一个类时,可以使用下面的修饰符:

  1. : base

    • 描述:冒号(:)表示继承,后面跟着基类名。
    • 例如:public class SportsCar : Car { ... }
  2. virtual

    • 描述:在基类中,将方法声明为virtual,允许在派生类中被重写。
    • 例如:public virtual void StartEngine() { ... }
  3. override

    • 描述:在派生类中,用于重写基类中的virtual方法。
    • 例如:public override void StartEngine() { ... }
  4. new

    • 描述:用于隐藏继承的同名成员。
    • 例如:public new string Color { get; set; }
  5. abstract

    • 描述:在抽象基类中,将方法声明为抽象,迫使派生类实现它。
    • 例如:public abstract void StartEngine();
  6. sealed

    • 描述:阻止方法在派生类中被重写。
    • 例如:public sealed override void StartEngine() { ... }

继承是面向对象编程中的一个重要概念,它允许代码的重用和扩展。

7.2.3 类的成员

在C#中,类的成员是可以由类的对象(实例)或类本身来调用的元素。以下是类成员的详细分类和描述:

局部变量

  • 描述:局部变量是在方法、构造函数或块内部声明的变量,它们只在这些范围内有效。
  • 示例
    void DisplayMessage()
    {
        string message = "Hello";
        Console.WriteLine(message);
    }
    

字段

  • 描述:字段是类中声明的变量,可以是静态的(类级别)或实例的(对象级别)。

    • 静态字段:属于类,而不是类的任何特定对象。
    • 实例字段:每个对象实例拥有自己的副本。
    • 常量:字段值在初始化后不能改变。
    • 只读字段:字段可以在构造函数中初始化一次,之后不能修改。
  • 示例

    public class Person
    {
        public const int MaxPersons = 100; // 常量
        public string Name; // 实例字段
        private int _age; // 私有实例字段
        public readonly int ID; // 只读字段
    }
    

方法成员

  • 描述:方法包含执行特定任务的代码。

    • 静态方法:通过类直接调用,不依赖于类的实例。
    • 实例方法:需要类的实例来调用。
  • 示例

    public class Calculator
    {
        public static int Add(int a, int b) // 静态方法
        {
            return a + b;
        }
    
        public int Multiply(int a, int b) // 实例方法
        {
            return a * b;
        }
    }
    

属性

  • 描述:属性提供了访问类中字段的安全方式,可以有getset块。
  • 示例
    public class Product
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
    }
    

事件

  • 描述:事件是一种特殊的多播委托,用于类之间的松散耦合。
  • 示例
    public class Publisher
    {
        public event EventHandler UpdateEvent;
        
        public void DoSomething()
        {
            UpdateEvent?.Invoke(this, EventArgs.Empty);
        }
    }
    

索引指示器

  • 描述:允许对象被像数组一样通过索引访问。
  • 示例
    public class ListDictionary
    {
        private Dictionary<int, string> _dictionary = new Dictionary<int, string>();
        
        public string this[int index]
        {
            get { return _dictionary[index]; }
            set { _dictionary[index] = value; }
        }
    }
    

操作符重载

  • 描述:允许已定义的类使用特定的C#操作符。
  • 示例
    public class Point
    {
        public int X, Y;
        public static Point operator +(Point p1, Point p2)
        {
            return new Point { X = p1.X + p2.X, Y = p1.Y + p2.Y };
        }
    }
    

构造函数和析构函数

  • 描述

    • 构造函数:在创建对象时初始化对象的方法,可以有多个(带不同参数)。
    • 析构函数:在对象被销毁前执行的方法,用来执行清理工作。
  • 示例

    public class Car
    {
        public Car()
        {
            Console.WriteLine("Car is created.");
        }
        
        ~Car()
        {
            Console.WriteLine("Car is destroyed.");
        }
    }
    

示例代码:组合类成员

以下是组合使用类成员的示例:

using System;

public class Car
{
    public string Brand { get; set; }
    private int _year;
    public int Year
    {
        get { return _year; }
        set { _year = value > 0 ? value : throw new ArgumentException("Year must be positive."); }
    }

    public Car(string brand, int year)
    {
        Brand = brand;
        Year = year;
    }
    
    public void StartEngine()
    {
        Console.WriteLine("Engine started.");
    }

    public event EventHandler Started;

    protected virtual void OnStarted()
    {
        Started?.Invoke(this, EventArgs.Empty);
    }

    public override string ToString()
    {
        return $"Car: {Brand}, Year: {Year}";
    }
}

public class Program
{
    public static void Main()
    {
        Car myCar = new Car("Toyota", 2021);
        myCar.Started += (sender, e) => Console.WriteLine("Car event started.");
        myCar.StartEngine();
        Console.WriteLine(myCar);
    }
}

在这个示例中,Car类使用了属性、方法、事件、构造函数和析构函数等类成员。Main方法展示了如何创建和使用Car对象。

7.2.4 类成员访问修饰符

在C#中,类成员访问修饰符用于控制类成员的可访问性。以下是常用的类成员访问修饰符及其描述:

修饰符描述
private私有成员只能在定义它的类内部访问。
protected保护成员可以在定义它的类及其派生类中访问。
public公共成员可以被任何其他类或实例访问。
internal内部成员只能在同一个程序集中访问。

访问修饰符的示例代码

以下是使用这些访问修饰符的示例:

public class Animal
{
    // 私有字段,只能在Animal类内部访问
    private string privateName;

    // 保护字段,可以在Animal类及其派生类中访问
    protected string protectedName;

    // 公共属性,可以被任何类访问
    public string PublicName { get; set; }

    // 内部字段,只能在同一个程序集中访问
    internal string InternalHabitat;

    // 私有方法,只能在Animal类内部调用
    private void PrivateMethod()
    {
        Console.WriteLine("Private method.");
    }

    // 保护方法,可以在Animal类及其派生类中调用
    protected void ProtectedMethod()
    {
        Console.WriteLine("Protected method.");
    }

    // 公共方法,可以被任何类调用
    public void PublicMethod()
    {
        Console.WriteLine("Public method.");
    }

    // 内部方法,只能在同一个程序集中调用
    internal void InternalMethod()
    {
        Console.WriteLine("Internal method.");
    }
}

public class Dog : Animal
{
    public Dog()
    {
        // 可以访问继承的保护成员和公有成员
        protectedName = "Canine";
        PublicName = "Dog";

        // 不能直接访问私有成员,但可以通过公共或保护方法间接访问
        PrivateMethod();
    }

    protected void ShowProtectedMethod()
    {
        ProtectedMethod();
    }
}

public class Program
{
    public static void Main()
    {
        Animal myAnimal = new Animal();
        Dog myDog = new Dog();

        // 可以访问公有成员
        myAnimal.PublicName = "Animal";

        // 不能直接访问私有成员或保护成员
        //privateName = "Incorrect";
        //protectedName = "Incorrect";

        // 内部成员只能在同一个程序集中访问
        //Animal internalAnimal = new Animal();
        //internalAnimal.InternalHabitat = "Incorrect";
    }
}

说明

  1. 私有成员(private:只能在定义它的类内部访问。例如,privateName只能在Animal类内部访问。

  2. 保护成员(protected:可以在定义它的类及其派生类中访问。例如,protectedName可以在Animal类及其派生类如Dog中访问。

  3. 公共成员(public:可以被任何其他类或实例访问。例如,PublicName属性可以被任何类访问和修改。

  4. 内部成员(internal:只能在同一个程序集中访问。例如,InternalHabitat只能在同一个程序集中的其他类中访问。

派生类访问基类成员

派生类可以继承基类的成员,但访问级别取决于基类成员的访问修饰符:

  • 私有成员(private:不能被派生类直接访问。
  • 保护成员(protected:可以在派生类中访问。
  • 公共成员(public:可以在派生类中访问。
  • 内部成员(internal:如果派生类在同一个程序集中,可以访问。

这些访问修饰符提供了封装和信息隐藏的机制,有助于保护类成员不被外部直接访问和修改,从而提高代码的安全性和可维护性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值