一、方法(函数)
方法就是把完成某一个独立功能的代码抽取出来封装成一个代码块。
好处:①代码复用,不用重复写;②逻辑清晰,方便维护;③便于调试修改。
1、方法的定义:
[访问修饰符] 返回值类型 方法名([参数列表])
{
//方法体
}
访问修饰符:public公开,哪里都可以调用;private仅本类内部使用。
static:静态方法,可以直接类名调用;没有 static 叫实例方法,必须 new 对象调用。
返回值类型:不需要返回数据写void;如果要返回数据,写对应数据类型,方法内部必须使用return,不写的话会报错,return作用包括:将数据返回给调用处;立刻结束当前这个方法,后面代码不会执行。
方法命名规范:大驼峰命名法,每个单词首字母大写。
参数列表:完成功能需要的外部传入的数据;没有参数小括号不能省略,其中参数列表可有可无,根据具体需求设置参数。
2. 方法的 4 大类
1、无参无返回值:public static void SayHi(){}
2、无参有返回值:public static int GetMax(){ return 10; }
3、有参无返回值:public static void PrintNum(int num){}
4、有参有返回值:public static int Add(int a,int b){ return a+b; }
调用:同个类里面直接写方法名(实参);不同类使用类名.方法名(实参)。
3. 实参与形参
1、形参:方法定义括号里面的变量,相当于占位符。
2、实参:调用方法的时候,传入的真实数据。、
4. 参数传递机制
1、值类型--值传递
包括整形,浮点型,字符形,结构体等数值类型,其用法是将形参值赋给另一形参值,在方法类的参数值不受方法外值的影响,因为二者在内存中为两块独立栈。
如:
结果为:
2、引用类型--引用传递
包括数组,string,类等数值类型,其用法是将形参值赋给另一形参值,在方法类的参数值受方法外值的影响,因为二者为同一堆内存。
注:如果方法内定义了新实例,则方法外形参不受影响。
二、面向对象--封装
封装:将字段私有化,对外暴露可控访问入口,隐藏内部细节,保护数据安全。其核心思想为:字段私有,属性公开访问。
1、访问修饰符
1、private:私有,只有当前类可以访问,字段一般都用 private 修饰。
2、protected:受保护,本类、继承的子类可以访问,外部不行。
3、public:完全公开,任何地方都能访问。
2. 属性 get /set
1、get:读取字段的值
2、set:给字段赋值;关键字value代表调用方传入的值。
例如在一个Person类里
3、构造函数
1、方法名和类名完全一模一样;没有返回值,不能写 void。
2、使用new 类名()创建对象的时候,会自动执行构造函数;构造函数的作用就是给对象属性做初始化。
3、构造函数可以重载(多个构造,参数列表不同)。
4、如果完全不手写任何构造函数,编译器自动赠送一个无参构造函数;一旦手写了有参构造,编译器不再提供默认无参,需要我们手动写出来。
4.static 静态
1、被 static 修饰的成员属于类本身,不属于实例对象。直接类名.成员名调用,不需要 new 对象。
2、静态成员在类加载的时候就分配内存,优先于对象存在。
3、静态方法里面不能直接访问实例成员(非静态属性、方法),不能使用 this 关键字。
4、实例方法(没有 static)既可以访问实例成员,也可以访问静态成员。
5、static 静态变量所有对象共享同一份数据。
三、继承 Inheritance
继承:class 子类 : 父类;子类复用父类已经写好的代码,描述 is‑a 的关系。
注:继承中是单继承,即子类只能有一父类,不能同时继承多个父类,但支持多层继承。
1、子类可以继承父类public、protected成员;不会继承父类 private 私有字段,但是可以通过 public 属性间接使用。
2、base关键字
base.成员名:在子类中访问父类的属性、方法。
base(参数):子类构造函数调用父类的构造函数,必须写在构造函数第一行。
在主程序中实例化对象时,会先调用父类的构造函数,后调用子类构造函数。
四、抽象类 abstract
当父类知道子类应该拥有什么行为,但是父类不知道这个行为具体怎么实现,就可以定义抽象类。
1、abstract修饰的类叫抽象类。
2、抽象方法:public abstract void Eat();,只有方法声明,没有方法体。
3、包含抽象方法的类,必须是 abstract 抽象类。
4、注:抽象类不能 new 创建实例对象。
5、如果普通类继承抽象类,必须重写抽象类里面全部抽象方法,使用 override。
6、抽象类可以拥有普通字段、普通属性、普通方法、可以拥有构造函数(供子类 base 调用初始化数据)。
7、限制:abstract不能和private、static一起修饰方法。
private:子类看不见,无法重写;
static:可以直接类名调用,但是抽象没有方法体,毫无意义。
五、接口 interface
接口代表一套行为规范、契约。接口只规定 “你应该拥有哪些功能”,不关心怎么实现。
1、使用interface关键字定义;类使用:来实现接口,不是继承。
2、接口不能有字段,不能写构造函数;里面全部是抽象成员(方法、属性)。
3、接口不能 new 实例。
4、C# 类可以实现多个接口,弥补类单继承的缺陷。class Dog:IEat,IRun,ISwim{}
5、接口和接口之间可以多继承。
例如
抽象类和接口区别:
| 对比项 | abstract 抽象类 | interface 接口 |
|---|---|---|
| 父子关系 | 类只能继承一个抽象类 | 类可以实现多个接口 |
| 字段 | 允许写字段、常量 | 不允许写任何字段 |
| 方法 | 抽象方法 + 完整有方法体普通方法 | 全部都是抽象方法 |
| 构造函数 | 可以有构造函数 | 没有构造函数 |
| 设计定位 | 描述这一类事物是什么 | 描述具备哪些功能行为 |
六、多态
动态多态有三个必要条件,缺一不可:1、继承;2、父类虚方法,子类重写;3、父类引用变量指向子类实例对象。
最后,这篇文章重点总结:
1、子类继承父类,子类构造默认调用父类无参构造;父类没有无参构造子类编译报错,需要写base()指定调用父类有参构造。
2、out 必须方法内部赋值;ref 调用前外部变量必须赋值。
3、抽象类可以有构造函数;接口绝对没有构造函数。
4、类单继承,接口多实现。
5、重写必须 virtual+override;重载只要求参数列表不同。
6、值传递复制数值,不会改变外部;引用类型传递地址,修改对象内部数据外部同步变化。
7、static 属于类,实例属于对象;静态方法不能访问实例成员,不能用 this。