C#之override(重写)与overload(重载)
一,overload(重载)
方法重载在鄙人以前博客中有详细介绍,这里提供一个案例进行参考
C#之实例化对象和方法重载
重载的案例;
在新建的类中创建方法
namespace lianxi
{
class A
{
public A()
{
Console.WriteLine("方法重载;方法名称一样");
}
public A(string name, int nl)
{
Console.WriteLine("方法重载;参数个数不一样");
}
public A(int nl, string name)
{
Console.WriteLine("方法重载;参数顺序不一样");
}
public A(int nl, double sg)
{
Console.WriteLine("方法重载;参数类型不一样");
}
}
}
在主程序中进行调用
namespace lianxi
{
class Program
{
static void Main(string[] args)
{
A cz = new A();
A cz1 = new A(12, "张三");
A cz2 = new A("李四", 20);
A cz3 = new A(45, 3.14);
Console.ReadLine();
}
}
}
最后的显示的结果
方法重载;方法名称一样
方法重载;参数顺序不一样
方法重载;参数个数不一样
方法重载;参数类型不一样
在这个博客中我们重点讲解override(重写)和它们两个之间的区别.
二,override(重写)
1,什么是重写?
-
重写父类方法就是修改它的实现方式或者说在子类中对它进行重新编写。
-
重写发生在有继承关系的类之间
-
重写是子类的方法覆盖父类的方法,要求方法名还有参数都必须相同
-
重写发生在子类上,通过override关键字来改写从其父类继承过来的具有相同返回值,方法名称和参数列表的方法。
2,为什么要重写呢?
通常,子类继承父类的方法,在调用对象继承方法的时候,调用和执行的是父类的实现,而且子类中默认是不允许出现和父类中方法名和参数相同的方法的。但是,我们有时候需要对子类中的继承方法有不同的实现方式。所以我们需要进行重写.
3,重写的前提?
-
参数列表必须完全与被重写的方法相同,否则不能称其为重写而是重载。
-
返回的类型必须一直与被重写的方法的返回类型相同,否则不能称其为重写而是重载。
-
重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常.
-
例如:父类的一个方法申明了一个检查异常IOException,在重写这个方法是就不能抛出Exception,只能抛出IOException的子类异常,可以抛出非检查异常。
-
访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private)
-
要重写父类的方法,前提是父类中该要被重写的方法必须声明为virtual(虚拟)或者是abstract(抽象)类型。
4,怎么重写?
- 重写父类的方法要用到override关键字(具有override关键字修饰的方法是对父类中同名方法的新实现)
- 给父类中要被重写的方法添加virtual(虚拟)关键字表示可以在子类中重写它的实现。C#中的方法默认并不是virtual(虚拟)类型的,因此要添加virtual(虚拟)关键字才能够被重写,abstract(抽象)也可以.
- virtual(虚拟)关键字用于将方法定义为支持多态,有virtual(虚拟)关键字修饰的方法称为“虚拟方法”
5,重写时父类中的语法
[访问修饰符] virtual [返回类型] 方法名(参数列表)
{
//虚拟方法的实现,该方法可以被子类重写
}
6,重写的案例
虚拟方法
- (虚拟方法)在父类中创建虚拟(virtual)方法
class A
{
//虚拟方法;关键字virtual
public virtual void dog()//虚拟方法
{
Console.WriteLine("父类中的虚拟方法:我叫哈士奇");
}
public virtual void cat()//虚拟方法
{
Console.WriteLine("父类中的虚拟方法:我叫小猫咪");
}
public void eat()//普通方法
{
Console.WriteLine("我是哈爷,我爱吃空气");
}
}
- (虚拟方法)在子类继承父类之后,我们对父类中的虚拟方法进行重写(override)
- 重写以后子类就会将父类中的虚拟方法进行覆盖,最后的结果不会显示父类中的方法,只会显示我们在子类重写以后的方法
- 除非我们输入(base.[父类中的方法名称])父类的方法就不会被覆盖,依旧可以显示
class B:A
{
public override void dog()//重写的虚拟方法
{
base.dog();//重写以后如果想调用父类中的方法则输入base.[父类中的方法名称]
Console.WriteLine("子类中重写以后的方法:我改名了,我叫哈爷");
}
public override void cat()//重写的虚拟方法
{
base.cat();//重写以后如果想调用父类中的方法则输入base.[父类中的方法名称]
Console.WriteLine("子类中重写以后的方法:我也改名了,我叫瞄崽");
}
}
- (虚拟方法)在主程序入口实例化子类进行调用
class Program
{
static void Main(string[] args)
{
B cx = new B();//实例化子类
//调用虚拟方法
cx.dog();
cx.cat();
cx.eat();
Console.ReadLine();
}
}
- (虚拟方法)没有输入(base.[父类中的方法名称])的显示结果
子类中重写以后的方法:我改名了,我叫哈爷
子类中重写以后的方法:我也改名了,我叫瞄崽
我是哈爷,我爱吃空气
- (虚拟方法)输入(base.[父类中的方法名称])的显示结果
父类中的虚拟方法:我叫哈士奇
子类中重写以后的方法:我改名了,我叫哈爷
父类中的虚拟方法:我叫小猫咪
子类中重写以后的方法:我也改名了,我叫瞄崽
我是哈爷,我爱吃空气
抽象方法
- (抽象方法)在父类中创建抽象(abstract)方法
- 一旦一个方法被声明为抽象方法(abstract)则该方法不能有主体(具体的实现)
- 而且该方法所对应的类,必须是抽象的类
abstract class A
{
//抽象方法;关键字abstract
public abstract void Junk();//抽象方法
public abstract void He();//抽象方法
}
- (抽象方法)在子类继承父类之后,我们对父类中的抽象方法进行重写(override)
- 一个子类继承了一个抽象类,那么子类必须重写父类中所有的抽象方法
class B:A
{
public override void Junk()
{
Console.WriteLine("子类中重写的抽象方法我喜欢喝可乐");
}
public override void He()
{
Console.WriteLine("子类中重写的抽象方法:我喜欢喝雪碧");
}
}
- (抽象方法)在主程序入口实例化子类进行调用
class Program
{
static void Main(string[] args)
{
B cx = new B();//实例化子类
//调用抽象方法
cx.Junk();
cx.He();
Console.ReadLine();
}
}
- (抽象方法)最后的显示结果为
子类中重写的抽象方法我喜欢喝可乐
子类中重写的抽象方法:我喜欢喝雪碧
7,重写要注意什么?
- 可以在子类中被重写的方法一定要被标记成virtual(虚拟), abstract(抽象), override(重写)标记为virtual 和abstract 的函数就是为了重写而创建的,标记为override的函数本身是由前两种函数重写而来的,所以它可以被重写也是顺理成章的了
- 重写的函数必须在子类中出现,而且任何一个父类的函数在其一个子类中只能被重写一次。
8,那么重写的意义是什么?
- 减少函数的数量,避免命名的污染,可应对不同的需求,针对同一母的不同情况
三,override(重写)与overload(重载)的区别?
1,定义上的区别:
-
重载是指不同的函数使用相同的函数名,但是函数的参数个数或类型以及顺序不同。调用的时候根据函数的参数来区别不同的函数。
-
重写(也叫覆盖)是指在子类中重新对父类中的虚拟函数或者抽象函数重新实现。即函数名和参数都一样,只是函数的实现体不一样。
2,规则上的区别:
(1),重载方法的规则:
-
重载返回值必须相同,否则不构成重载
-
重载实现于一个类
-
重载是编译时多态( 重载在编写代码过程中如果不符合方法重载规则,编译器会自动报错,为编译时多态。)
-
重载不用继承就可以实现
-
必须具有不同的参数列表。
-
可以有不同的访问修饰符。
-
可以抛出不同的异常。
(2),重写方法的规则:
-
重写返回值无关
-
重写实现于子类中
-
重写是运行时多态( 重写是代码运行中,执行到具体类别时,才会调用该类的重写为运行时多态。)
-
重写必须继承以后才可以实现
-
参数列表必须完全与被重写的方法相同,否则不能称其为重写而是重载。
-
返回的类型必须一直与被重写的方法的返回类型相同,否则不能称其为重写而是重载。
-
访问修饰符的限制一定要大于被重写方法的访问修饰符。
-
重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。
3,类的关系的区别:
- 重写是子类和父类之间的关系,是继承关系;重载是同一个类中方法之间的关系,是平值关系。
4,调用方式的区别:
- 重载相同的对象调用
- 重写不同的对象调用