天天看点

# C# 学习笔记(4) 类C# 学习笔记(4) 类

C# 学习笔记(4) 类

面向对象编程主要是为了写出一个通用的代码,屏蔽差异,方便开发大型项目。类就是面向对象编程的核心之一。和C语言的结构体相比,结构体拥有的功能,类统统都有,除此之外,类还有许多新特性。

类的构成

[其他修饰符] [访问修饰符] class 类名
{
	字段;
	属性;
	方法;
    构造函数;
    析构函数;
}
           

字段

存放类的私有数据,通常只能被类的属性访问。

属性

保护字段,对字段的赋值和取值进行限定。例如有一个学生类,类中有成绩这个字段,类外只可以获取到成绩的等级–优良中差,这时就可以给这个字段加上一个属性,通过访问属性间接访问成绩字段。为了保证程序封装性,类外一般是不允许访问类内的字段的,一般字段和属性是成对出现的。
public class Student
    {
        int _Score;    //成绩字段
        public string Score   //成绩属性
        {
            get 
            { 
                if(_Score < 60)
                {
                    return "差";
                }
                else if(_Score < 80)
                {
                    return "中";
                }
                else if(_Score < 90)
                {
                    return "良";
                }
                else
                {
                    return "优";
                }
            }
            set 
            { 
                _Score = int.Parse(value); 
            }
        }
    }
           

属性的本质就是两个方法,一个叫get()一个叫set()。

既有get()也有set()我们诚之为可读可写属性。

只有get()没有set()我们称之为只读属性

没有get()只有set()我们称之为只写属性

方法

方法也就是C语言中的函数,面向对象里面叫方法。
  • C语言中,函数名字不能重复,而C#中允许方法名重复(方法重载),不过要求方法参数要么个数不同,要么类型不同。
public class Student
    {
        int _Score;    //成绩字段
        public string Score   //成绩属性
        {
            get 
            { 
                if(_Score < 60)
                {
                    return "差";
                }
                else if(_Score < 80)
                {
                    return "中";
                }
                else if(_Score < 90)
                {
                    return "良";
                }
                else
                {
                    return "优";
                }
            }
            set { _Score = int.Parse(value); }
        }
        //三个方法名字都叫Learn 方法1、2参数个数相同但是类型不同 方法1、3参数类型相同但是个数不同
        public void Learn(string subject, int time)
        {
            Console.WriteLine("学习{0}科目, 学习时长:{1}", subject, time);
        }
        public void Learn(string subject1, string subject2)
        {
            Console.WriteLine("学习{0}科目, 学习{1}科目", subject1, subject2);
        }
        public void Learn(string subject, int time, float ratio)
        {
            Console.WriteLine("学习{0}科目, 学习时长:{1}, 学习效率:{2}", subject, time, ratio);
        }
    }
           

构造函数

作用:帮助我们初始化对象(给对象的属性赋值)

构造函数是一个特殊的方法:

1)、构造函数没有返回值,连void也不能写。

2)、构造函数的名称必须跟类名一样。

  • 创建对象的时候会执行构造函数
  • 构造函数是可以有重载的。

类当中会有一个默认的无参数的构造函数,当你写一个新的构造函数之后,不管是有参数的还是

无参数的,那个默认的无参数的构造函数都被干掉了。

public class Student
    {
        int _Score;    //成绩字段
        public string Score   //成绩属性
        {
            get 
            { 
                if(_Score < 60)
                {
                    return "差";
                }
                else if(_Score < 80)
                {
                    return "中";
                }
                else if(_Score < 90)
                {
                    return "良";
                }
                else
                {
                    return "优";
                }
            }
            set 
            { 
                _Score = int.Parse(value); 
            }
        }
        //默认构造函数 也可以自己添加参数和方法体
        public Student()
        {

        }
    }
           

析构函数

作用:析构函数(destructor) 与构造函数相反,当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,应在退出前在析构函数中用delete释放)。
  • 区别于构造函数。它不能带任何参数,也没有返回值(包括void类型)。只能有一个析构函数,不能重载。如果用户没有编写析构函数,编译系统会自动生成一个缺省的析构函数,它也不进行任何操作。

    析构函数是一个特殊的方法:

    1)、析构函数不能被继承或重载。

    2)、析构函数不能被用户调用。

    3)、析构函数不能带修饰或参数。

    4)、如果没有析构函数系统会自动生成一个空的析构函数,对象使用的资源将有由GC Garbage Collection垃圾回收器回收(如果用户想要自己释放资源,则要自行 编写析构函数)

public class Student
    {
        int _Score;    //成绩字段
        public string Score   //成绩属性
        {
            get 
            { 
                if(_Score < 60)
                {
                    return "差";
                }
                else if(_Score < 80)
                {
                    return "中";
                }
                else if(_Score < 90)
                {
                    return "良";
                }
                else
                {
                    return "优";
                }
            }
            set 
            { 
                _Score = int.Parse(value); 
            }
        }
        //默认构造函数 也可以自己添加参数和方法体
        public Student()
        {

        }
        //默认析构函数 也可以自己添加方法体
        ~Student()
        {

        }
    }
           

修饰符

访问修饰符

  • public :公开的公共的
  • private:私有的,只能在当前类的内部访问
  • protected:受保护的,只能在当前类的内部以及该类的子类中访问。
  • internal:只能在当前项目中访问。在同一个项目中,internal和public的权限是一样。
  • protected internal:protected+internal

1)、能够修饰类的访问修饰符只有两个:public、internal。

2)、在继承中,当可访问性不一致时,

子类的访问权限不能高于父类的访问权限,否则会暴漏父类的成员。

其他修饰符

  • partial部分类
    在合作开发时,一个类可能由多个人写,每个人都写在不同的文件中,这时可以使用partial来修饰类,表示当前只是该类的一部分。
  • sealed密封类
    丁克,不能被继承
  • static

静态和非静态的区别

1)、在非静态类中,既可以有实例成员,也可以有静态成员。

2)、在调用实例成员的时候,需要使用对象名.实例成员;

在调用静态成员的时候,需要使用类名.静态成员名;

总结:静态成员必须使用类名去调用,而实例成员使用对象名调用。

静态函数中,只能访问静态成员,不允许访问实例成员。

实例函数中,既可以使用静态成员,也可以使用实例成员。

静态类中只允许有静态成员,不允许出现实例成员。

使用:

1)、如果你想要你的类当做一个"工具类"去使用,这个时候可以考虑将类写成静态的。

2)、静态类在整个项目中资源共享。

只有在程序全部结束之后,静态类才会释放资源。