重载和覆盖


103

重载和覆盖之间有什么区别。


2
@james:您至少尝试过Google吗?
米奇·

我猜你不会得到这个。
乔恩·B

詹姆斯-可能不是,我感到无法解释一个简单的概念很可笑

1
@james我的猜测是您在不知道术语的情况下就直觉了这些概念。我猜你是自学成才的。您可能应该拿起初学者级的C#书,而不是学习而是强化您已经知道的知识。这很令人麻木,但将在技术面试中极大地帮助您。
Michael Meadows

您可以在此链接上了解更多信息:intquesans.blogspot.com/2011/05/…– 2011

Answers:


218

超载

重载是指您在同一作用域中具有名称相同但签名不同的多个方法。

//Overloading
public class test
{
    public void getStuff(int id)
    {}
    public void getStuff(string name)
    {}
}

覆写

覆盖是允许您更改子类中方法功能的原理。

//Overriding
public class test
{
        public virtual void getStuff(int id)
        {
            //Get stuff default location
        }
}

public class test2 : test
{
        public override void getStuff(int id)
        {
            //base.getStuff(id);
            //or - Get stuff new location
        }
}

1
我喜欢这个答案@cgreeno ..谢谢
Ferrakkem Bhuiyan 2014年

1
@cgreeno我想你错过voidgetStufftest2
马赫迪

2
只需提一下,必须将基类方法标记为虚方法,以覆盖它,否则会出现编译错误。
亚历克斯·史蒂芬斯

嘿,这可能很旧了,但是我对此仍然有疑问。重载是否可以通过“一个”方法提供更多功能?就像我可以这样做:getStuff(2, "Hello world!");还是我可以做到这一点getStuff("Myname", "Mysurname", "Hello World!");?任何人都可以确认这是这样做的方法吗?
Sj03rs

我认为Overriding示例实际上是Overwrite,Override是当您超类方法意外获得Override时,或者如果您打算通过两种情况都使用new关键字来进行Override或Overwrite覆盖,则在声明Parent p = new时,behaivor是不同的儿童(); p.Method(); ...也许我错了,这只是做几乎同一件事的另一种方法。谁能比我更好地解释它?
Cristina Carrasco

35

重载和覆盖的简单定义

重载(编译时多态)::具有相同名称和不同参数的函数

public class A
{
    public void print(int x, int y)
    {
        Console.WriteLine("Parent Method");
    }
}

public class B : A
{
    public void child()
    {
        Console.WriteLine("Child Method");
    }

    public void print(float x, float y)
    {
        Console.WriteLine("Overload child method");
    }
}

覆盖(运行时多态):扩展类中的函数,其名称和参数与基类中的名称和参数相同,但行为不同。

public class A
{
    public virtual void print()
    {
        Console.WriteLine("Parent Method");
    }
}

public class B : A
{
    public void child()
    {
        Console.WriteLine("Child Method");
    }

    public override void print()
    {
        Console.WriteLine("Overriding child method");
    }
}

也许您想补充一点,即覆盖概念适用于父类-子类关系。
Freakyuser

10

我想分享一个例子,对我来说很有意义:

这只是一个示例,其中不包括虚拟方法或基类。只是为了提示有关主要思想。

假设有一台洗车机,它具有称为“洗车”的功能,并且接受Car作为一种类型。

获取汽车输入并清洗汽车。

public void Wash(Car anyCar){
       //wash the car
}

让我们重载Wash()函数

重载:

public void Wash(Truck anyTruck){
   //wash the Truck  
}

洗车功能以前只是洗车,但现在也可以洗车了。

  • 如果提供的输入对象是Car,它将执行Wash(Car anyCar)
  • 如果提供的输入对象是卡车,则它将执行Wash(Truck anyTruck)

让我们重写Wash()函数

覆盖:

public override void Wash(Car anyCar){
   //check if the car has already cleaned
   if(anyCar.Clean){ 
       //wax the car
   }
   else{
       //wash the car
       //dry the car
       //wax the car
   }     
}

清洗功能现在可以检查汽车是否已经清洁,无需再次清洗。

  • 如果汽车清洁,则只需上蜡。

  • 如果不干净,请先洗车,然后干燥,然后上蜡

因此,通过添加新功能或做一些完全不同的事情,该功能已被覆盖。


1
这一定是答案。投票+
杰克


4

正如迈克尔所说:

  • 重载=多个方法签名,相同的方法名称
  • 覆盖=相同的方法签名(声明为虚拟),在子类中实现

  • 阴影=如果视为DerivedClass,则使用派生方法;如果作为BaseClass,则使用基本方法。

3

具有相同名称但参数不同的多个方法/构造函数称为重载。这是一个编译时事件。

Class Addition 
{
   int add(int a, int b) 
   {
     return a+b;
   }
   int add(int a, int b, int c)
   {
     return a+b+c;
   }

   public static main (String[] args) 
   {
     Addition addNum = new Addition();
     System.out.println(addNum.add(1,2));
     System.out.println(addNum.add(1,2,3));
   }
}

O / p:

3
6

覆盖是运行时事件,这意味着基于您的代码,输出在运行时会更改。

class Car
{
    public int topSpeed() 
    {
        return 200;
    }
}
class Ferrari extends Car
{
    public int topSpeed()
    {
        return 400;
    }
    public static void main(String args[])
    {
        Car car = new Ferrari();
        int num= car.topSpeed();
        System.out.println("Top speed for this car is: "+num);
    }
}

注意,两个类topSpeed()中都有一个通用方法。自实例化法拉利以来,我们得到了不同的结果。

O / p:

Top speed for this car is: 400

2

在C#中,没有Java之类的隐藏覆盖,没有在覆盖方法上使用关键字覆盖!请参阅以下C#实现:

变量1无覆盖:结果为200

    class Car {
        public int topSpeed() {
            return 200;
        }
    }

    class Ferrari : Car {
        public int topSpeed(){
                return 400;
        }
    }

    static void Main(string[] args){
        Car car = new Ferrari();
        int num= car.topSpeed();
        Console.WriteLine("Top speed for this car is: "+num);
        Console.ReadLine();
    }

带有替代关键字的变体2 :结果为400

    class Car {
        public virtual int topSpeed() {
            return 200;
        }
    }

    class Ferrari : Car {
        public override int topSpeed(){
                return 400;
        }
    }

    static void Main(string[] args){
        Car car = new Ferrari();
        int num= car.topSpeed();
        Console.WriteLine("Top speed for this car is: "+num);
        Console.ReadLine();
    }

Car类上的关键字virtual相对于Java上的final是相反的,表示不是final,您可以覆盖或实现,如果Car是抽象的


1

shadowing =在派生类中维护两个定义,并且为了投影基类定义,将其阴影(隐藏)派生类定义,反之亦然。


1

补充一点。

重载多个具有相同名称的方法。相同或不同的返回类型。参数编号不同或参数类型不同。在同一个类或派生类中。

int Add(int num1,int num2)int Add(int num1,int num2,int num3)double Add(int num1,int num2)double Add(double num1,double num2)

可以在同一类或派生类中使用。一般喜欢同班。例如Console.WriteLine()有19个重载方法。

可以重载类的构造函数,方法。

可以认为是编译时(静态/早期绑定)多态性。

================================================== ================================================== =

在同一个类中无法覆盖。可以覆盖类的方法,属性,索引器,事件。

有一些限制,例如Override的基本方法必须是虚的,抽象的或Override。您不能使用新的,静态的或虚拟的修饰符来修改覆盖方法。

可以视为运行时(动态/后期绑定)多态。

帮助进行版本控制http://msdn.microsoft.com/zh-cn/library/6fawty39.aspx

================================================== ================================================== =

有用的网址

http://msdn.microsoft.com/zh-cn/library/ms173152.aspx 编译时多态与运行时多态


好一个,有必要的细节。
user3885927's

1

重载是静态多态性的一部分,用于实现名称相同但签名不同的不同方法。覆盖用于完成不完整的方法。我认为这两个概念之间没有可比性,唯一相似的是两者都有相同的词汇。


队长在这里:重载方法会给您多个具有相同名称的不同方法的签名。覆盖从类或接口中隐藏继承的成员。飞走了
-SparK

1
@SparK覆盖不会隐藏成员。你可以任意重写隐藏继承成员。两者是互斥的选项。
Servy

@Servy,错误的单词选择,我的意思是“替代”。
SparK's

0

方法重载和方法重写是两个完全不同的概念。方法重载具有相同的方法名称,但具有不同的签名。方法重写正在更改派生类中基类方法的默认实现。在下面,您可以找到2个出色的视频教程,解释了这些概念。

替代隐藏的方法

方法重载


0

重载是一个概念,其中您具有相同的签名或具有相同名称的方法,但具有不同的参数和覆盖,我们具有具有不同参数的相同名称的方法也具有继承,这称为覆盖。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.