覆盖与重载(override/overload) [C#]

1. 方法签名与方法的显式隐藏

    以下程序中,子类B与父类A存在签名相同的函数,将产生方法隐藏。由于没有显式使用new修饰符,编译时出现警告。
签名相同简单的讲是指忽略访问控制符、函数返回值、参数名后其它内容相同。
如:internal int Print(int x)
     public void Print(int y)
     protected float Print(int z)
    忽略访问控制符、返回值与参数名后都变成了Print(int),所以它们都是签名相同的函数。
      public int Print(int x, int y) 和 public int Print(int x) 属于不同签名的函数
      public int Print(int X) 和 public int Print(float x) 属于不同签名的函数
    当new关键字用作修饰符时,可以在派生类中隐藏基类的方法,也就说在派生类的方法是new关键字新定义出来的方法,而不是基类的方法。在不使用New关键字来隐藏基类方法也是可以的,编译器会出现一个警告,提示如果有意隐藏基类的方法,请使用New关键字修饰。
    这种方法不应该过多地使用,因为它破坏了类型之间良好的继承关系,容易造成理解和维护上的困难。

using  System;
using  System.Collections.Generic;
using  System.Text;

namespace  LearnCSharp
{
    
class A
    
{
        
internal void Print(int x)
        
{
            Console.WriteLine(
"A: {0}", x);
        }

    }


    
class B : A
    
{
        
//当A中的Print()成员用public、protected、internal修饰,B从A继承了Print()方法时,会出现如下警告:
        
//"LearnCSharp.B.Print()"隐藏了继承的成员"LearnCSharp.A.Print()",如果是有意隐藏,请使用关键字new
        public void Print(int y)
        
{
            Console.WriteLine(
"B: {0}", y);
        }

    }


    
class P
    
{
         
public static void Main(string[] args)
         
{
             A a 
= new A();
             a.Print(
3);
             Console.ReadKey();

             B b 
= new B();
             b.Print(
4);
             Console.ReadKey();
         }
 
    }

  
}
输出:
A: 3
B: 4


用关键字new,"LearnCSharp.B.Print()"显式隐藏了继承的成员"LearnCSharp.A.Print()":
using  System;
using  System.Collections.Generic;
using  System.Text;

namespace  LearnCSharp
{
    
class A
    
{
        
internal void Print(int x)
        
{
            Console.WriteLine(
"A: {0}", x);
        }

    }


    
class B : A
    
{
        
public new void Print(int y)
        
{
            Console.WriteLine(
"B: {0}", y);
        }

    }


    
class P
    
{
         
public static void Main(string[] args)
         
{
             A a 
= new A();
             a.Print(
3);
             Console.ReadKey();

             B b 
= new B();
             b.Print(
4);
             Console.ReadKey();
         }
 
    }

  
}
输出:
A: 3
B: 4


把基类中的Print()方法变成virtual方法后:
using  System;
using  System.Collections.Generic;
using  System.Text;

namespace  LearnCSharp
{
    
class A
    
{
        
internal virtual void Print(int x)
        
{
            Console.WriteLine(
"A: {0}", x);
        }

    }


    
class B : A
    
{
        
//警告:"LearnCSharp.B.Print()"将隐藏继承的成员"LearnCSharp.A.Print()"。若要使当前成员重写该实现,
        
//请添加关键字override,否则添加关键字new。
        public void Print(int y)
        
{
            Console.WriteLine(
"B: {0}", y);
        }

    }


    
class P
    
{
         
public static void Main(string[] args)
         
{
             A a 
= new A();
             a.Print(
3);
             Console.ReadKey();

             B b 
= new B();
             b.Print(
4);
             Console.ReadKey();
         }
 
    }

  
}
输出:
A: 3
B: 4


添加override关键字后:
using  System;
using  System.Collections.Generic;
using  System.Text;

namespace  LearnCSharp
{
    
class A
    
{
        
public virtual void Print(int x)
        
{
            Console.WriteLine(
"A: {0}", x);
        }

    }


    
class B : A
    
{
        
public override void Print(int y)
        
{
            Console.WriteLine(
"B: {0}", y);
        }

    }


    
class P
    
{
         
public static void Main(string[] args)
         
{
             A a 
= new A();
             a.Print(
3);
             Console.ReadKey();

             B b 
= new B();
             b.Print(
4);
             Console.ReadKey();
         }
 
    }

  
}
输出:
A: 3
B: 4

添加关键字abstract将类A变成抽象类后,无法创建抽象类或接口“LearnCSharp.A”的实例。修改后为:
using  System;
using  System.Collections.Generic;
using  System.Text;

namespace  LearnCSharp
{
    
abstract class A
    
{
        
public virtual void Print(int x)
        
{
            Console.WriteLine(
"A: {0}", x);
        }

    }


    
class B : A
    
{
        
public override void Print(int y)
        
{
            Console.WriteLine(
"B: {0}", y);
        }

    }


    
class P
    
{
         
public static void Main(string[] args)
         
{
             B b 
= new B();
             b.Print(
4);
             Console.ReadKey();
         }
 
    }

  
}
输出:
B: 4


以下程序展示了new和override的本质区别
using  System;
using  System.Collections.Generic;
using  System.Text;

namespace  LearnCSharp
{
    
abstract class A
    
{
        
public virtual void Print()
        
{
            Console.WriteLine(
"这是虚方法");
        }

    }


    
class B1 : A
    
{
        
public override void Print()
        
{
            Console.WriteLine(
"这是新的方法");
        }

    }


    
class B2 : A
    
{
        
public new void Print()
        
{
            Console.WriteLine(
"这是另一个新的方法");
        }

    }


    
class P
    
{
         
public static void Main(string[] args)
         
{
             A a1 
= new B1();
             A a2 
= new B2();
             a1.Print();
             a2.Print();
             Console.ReadKey();
         }
 
    }

  
}
输出:
这是新的方法
这是虚方法

    总结:New关键字主要用来区别派生类和基类同名方法的选择问题,通过隐藏基类方法,达到使编译器调用正确的方法的目的。Override主要用来对基类的方法和虚方法进行重写。

2. 方法重载与重写(overload & override)

    override表示“重写”,用于继承一个基类的时候,基类当中虚拟成员的实现。一般语境里,如果说这个method(方法)是被override来的,就是说在定义这个方法的类的父类中有一个与这个方法同名且参数类型列表相同的方法,在子类中,这个方法被override了。在对这个子类的实例调用该方法时,编译器确切的知道调用的是这个子类的方法。override指它随时随地都只有一种含义。
    overload表示“重载”,用于同一类中同名方法但参数个数或类型不同的实现,也就是让方法有不同签名的版本。一般语境里overload是对method(方法)而言的,可以指一个类中多个名字相同而参数类型列表不相同的方法,这个名字代表的方法就是被overload了的。编译器会根据参数类型列表的不同来决定调用叫这个名字的很多方法中具体的哪一个。指同样的东西在不同的地方具有多种含义。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值