C#笔记[ 三 ]:多态与继承,重载和重写

Evernote Export

 

 
.................................. C#的 多态和继承,重载和重写 ...................................
C#的多态
多态是由 继承来实现的
静态多态性
函数重载
相同的函数名有多个定义,参数列表一定不相同;返回值类型可以相同,也可以不相同
动态多态性
继承关系来
重写父类方法、
接口的实现
父类的实例调用被子类重写的方法
1.子类在继承父类的时候重写了父类中的方法
2.里氏转换原则
同一个方法,根据传入的参数不同,结果也不同,这就是多态
 
C#的继承
1. 继承中,除了构造函数、析构函数,还有 private 成员外,其他都被子类继承 [ 即子类中有一模一样的字段属性方法 ],
也都能被子类访问 [ 用 base 访问 ];this:代表该类的实例;base:代表父类的实例
 
2. C#会默认给没有创建构造函数的类[包括抽象类]创建一个无参的构造函数;如果给类创建了任何类型的构造函数,C#都不会默认再给该类创建构造函数
只要创建子类实例[ 不管有参/无参数 ],都会默认调用父类的无参构造函数,再调用子类相对应的构造函数 [所以作为父类的类一定要有无参构造函数]
如果创建子类实例[ 不管有参/无参数 ],想要调用父类的有参构造函数,在子类的构造函数上加base(参数...),多少个参数就调用父类的多少个参数的构造函数
new:覆盖
3. 子类里面定义一个和父类中相同的成员,会将父类继承来的成员,用 new 关键字覆盖掉
override:重写
重写父类中的方法;
只能重写用 abstractvirtual, override 修饰的方法
new 和 override
如果父类中方法成员不用修饰符,子类中只能使用 new 覆盖,
如果使用 virtual 修饰,可以用 new / override
4. 区别在于 里氏转化原则[ 子类的实例赋值给父类的变量 ]下 不同:
子类中用 new 覆盖父类的方法,会调用父类的方法;子类中用 override 重写父类的方法,会调用子类的方法
 
--------------------------------------------------------------------------------------------
<第1>子类中调用父类的方法
--- 子类只能在方法中 使用 从父类继承来的成员, 也只能在方法中 访问/调用 父类中的成员 [ 在类下的都是类自己的成员 ]
this:代表当前类的对象
base:代表父类中的对象
 
publicclassPerson
{
publicstringstr = "str";
publicvirtualvoidPrintC()
{
Console.WriteLine("A");
}
}
publicclassStudent : Person
{
publicvoidPrint()
{
base.PrintC(); // 调用父类中的方法
Console.WriteLine(this.str + " " + base.str); // 访问从父类中继承过来的 str
}
}
 
 
--------------------------------------------------------------------------------------------
<第2>创建子类的实例,会默认调用父类的无参构造函数,再调用子类相对应的构造函数
publicclassGrandfatherClass
{
publicstringstr = "123";
publicGrandfatherClass()
{
Console.WriteLine("GrandfatherClass 無參構造函數 ");
}
publicGrandfatherClass(string from1)
{
Console.WriteLine("GrandfatherClass 有1个參構造函數,參數爲:{0}", from1);
}
publicGrandfatherClass(string from4, string from5)
{
Console.WriteLine("GrandfatherClass 有2个參構造函數,參數爲:{0}", from4);
}
}
publicclassFatherClass : GrandfatherClass
{
publicFatherClass()
{
Console.WriteLine("FatherClass 無參構造函數");
}
publicFatherClass(string from2)
{
Console.WriteLine("FatherClass 有1个參構造函數,參數爲:{0}", from2);
}
publicFatherClass(string from2, string from3)
{
Console.WriteLine("FatherClass 有2个參構造函數,參數爲:{0}", from2);
}
}
publicclassMeClass : FatherClass
{
publicstringabc = "";
publicMeClass(string str, string str2):base(str) // 创建
{
Console.WriteLine("MeClass 有2个參構造函數,參數爲:{0}", str);
}
}
 
MeClass mc = newMeClass("str1","str2");
// GrandfatherClass 無參構造函數
// FatherClass 有1个參構造函數,參數爲 str1
// MeClass 有2个參構造函數,參數爲 str1
 
想要执行 FatherClass 中的 public FatherClass(string from2)
1. MeClass mc = new MeClass("str1","str2"); 创建了MeClass()的实例会调用 MeClass两个参数的构造函数
2. 想要调用 MeClass两个参数的构造函数,本来是调用 FatherClass无参的构造函数的,但是加了 base(str), 所以调用 public FatherClass(string from2)
3. 想要调用 public FatherClass(string from2), 调用其父类无参的构造函数 public GrandfatherClass()
 
 
--------------------------------------------------------------------------------------------
<第3,4>子类中定义和父类中同名的方法,调用子类的方法,是否会调用父类的方法 / 覆盖new 和重写override的区别
--- 调用方法只会调用一个方法,要么是父类的方法,要么是子类的方法;不会像 创建实例,调用多个构造函数
--- 里氏转换原则:调用的都是父类中从成员;如果想要调用子类的方法成员,需要在子类中使用 override 进行重写
 
classPerson
{
public virtual voidPrintC()
{
Console.WriteLine("A");
}
}
classLenader:Person
{
publicvoidPrintC()
{
Console.WriteLine("B");
}
}
 
classTeacher:Person
{
publicnewvoidPrintC()
{
Console.WriteLine("B");
}
}
classStudent:Person
{
publicoverridevoidPrintC()
{
Console.WriteLine("C");
}
}
 
Person person = newPerson();
person.PrintC(); // 输出A
Lenader stu2 = newLenader(); // 不使用里氏转化原则,子类的 PrintC()会隐藏了 父类的 PrintC()方法
stu2.PrintC(); // 输出B
Person stu2 = newTeacher(); // 里氏转化原则,用new覆盖,会调用父类的方法
stu2.PrintC(); // 输出A
 
Person stu3 = newStudent(); // 里氏转化原则,用override重写,会调用子类的方法
stu3.PrintC(); // 输出C
 
 
重载和重写
1. 重载:同一个类中,方法名相同,参数一定不相同,返回类型可以相同,也可以不相同
2. 重写:两个类中,子类重写从父类中继承来的方法 [ 包括子类重写父类是抽象类中的抽象方法和虚方法 ]


 
 
作者:大李子
邮箱:1185241994@qq.com
本文版权归作者所有,欢迎转载,未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利
 
 
posted @ 2021-03-06 22:21  大李子"  阅读(872)  评论(0)    收藏  举报