C#中级教程流水账
3.面对对象——继承
继承
实现继承:表明一个类派生于一个基类型,它拥有基类型的所有成员函数和字段。
接口继承:表明一个类型只继承了函数的名字,不继承具体的实现方法,这些需要开发人员自己继续实现。
多重继承
这种方式至今存在着争议,但还是说明一下,多重继承的优点是可以一次性继承很多类的成员函数和字段,但就会像一个爆发户一样,一次性得到大量的财富可能会使用的乱七八糟。 如果一个继承树中,从最早的最上面的基类到下面的后面的子类存在两条或以上的继承路径,将会导致子类会有两条或以上的基类构造路径,将会导致含有同名称的重复数据成员。
例:
public DataBase{};
public DataA{}:public DataBase{};
public DataB{}:public DataBase{};
public DataC{}:public DataA{},public DataB{};
虚方法
virtual void function();
这种被称作虚函数或者虚方法,可以在子类中使用override来改写函数的具体实现方法。
隐藏方法
如果基类中某个函数不是虚函数,但是我们还是想改写其方法,这时就用到隐藏方法了。
this和base关键字
this的作用有二:
1.访问这个类定义的字段方法,(其实没有也可以访问),有的话会让IDE提示把所有可以访问的字段都罗列。
2.当方法中的参数和你的字段名重复时,用this代表访问的是类中的字段。
base的作用:
1.用来访问父类的public方法和字段,和this同理,有了base可以让IDE有提示方便选择。
抽象类
1.声明成抽象类的类,不能去构造对象(实例化)
2.抽线类可以包含抽象函数和普通函数(抽象函数没有函数体)
密封类和密封方法
C#可以把类写成sealed:
这种类不能被继承,方法也不能重写
使用原因:商业原因;防止某些重写导致代码混乱。
派生类的构造函数
执行派生类的构造函数的时候,会先执行基类的构造函数,如果基类的构造函数不是无参的,那我们就必须给基类的构造函数一个实参,不然会报错。
下面的程序演示了派生类的构造函数和析构函数的调用顺序:
#include <iostream>
#include <string>
using namespace std;
class CBug {
int legNum, color;
public:
CBug(int ln, int c1) : legNum(ln), color(c1)
{
cout << "CBug Constructor" << endl;
};
~CBug()
{
cout << "CBug Destructor" << endl;
}
void Printlnfo()
{
cout << legNum << "," << color << endl;
}
};
class CFlyingBug : public CBug
{
int wingNum;
public:
//CFlyingBug(){} 若不注释掉则会编译出错
CFlyingBug::CFlyingBug(int ln, int c1, int wn) : CBug(ln, c1), wingNum(wn)
{
cout << "CFlyingBug Constructor" << endl;
}
~CFlyingBug()
{
cout << "CFlyingBug Destructor" << endl;
}
};
int main() {
CFlyingBug fb(2, 3, 4);
fb.Printlnfo();
return 0;
}
程序输出结果:
CBug Constructor
CFlyingBug Constructor
2,3
CFlyingBug Destructor
CBug Destructor
这里第25行必须注释,不然会报错。
第26行CBug(ln,cl)指明了在派生类对象在执行构造函数的时候,基类的初始化方式。
修饰符
常用的就不总结了
protect:只有派生类的可以访问
internal:只能在包含的程序集例访问
其他修饰符
static 适用于所有成员 成员不应用于具体实例。(这里static的用法指的是在面向对象的语言中)
如果你想要让类的一个成员不需要先创建对象再调用,而是直接进行调用的话,就在前面加一个static。
定义和实现接口
接口的声明方式
例:
public interface Fly
{
void fly(参数);
}
public plane:fly
{
public void fly(参数)
{
console.WriteLine("这里实现飞翔的具体方法");
}
}
派生的接口
接口可以彼此继承,其继承的方法和类相同