重载和重写(Overload, Override)

override和重载的区别? 
重载应该叫overload,重写叫override   
  重载某个方法是在同一个类中发生的!   
  重写是在子类中重写父类中的方法。

1.
父类:public virtual string ToString(){return "a";}
子类:public override string ToString(){return "b";}
2.
同一类中或父子关系类中皆可:
public string ToString(){return "a";}
public string ToString(int id){return id.ToString();}
override是用于重写基类的虚方法,这样在派生类中提供一个新的方法
重载是提供了一种机制, 相同函数名通过不同的返回值类型以及参数来表来区分的机制

1. override
-----------
使用 override 修饰符来修改方法、属性、索引器或事件。重写方法提供从基类继承的成员的新实现。由重写声明重写的方法称为重写基方法。重写基方法必须与重写方法具有相同的签名。
不能重写非虚方法或静态方法。重写基方法必须是虚拟的、抽象的或重写的。
也就是说,用 override 修饰符重写的基类中的方法必须是 virtual, abstract 或 override 方法。
 
2. 重载
-------
当类包含两个名称相同但签名不同的方法时发生方法重载。
使用重载方法的指南:
a. 用方法重载来提供在语义上完成相同功能的不同方法。
b. 使用方法重载而不是允许默认参数。默认参数的版本控制性能不好,因此公共语言规范(CLS)中不允许使用默认参数。
c. 正确使用默认值。在一个重载方法系列中,复杂方法应当使用参数名来指示从简单方法中假定的默认状态发生的更改。
d. 对方法参数使用一致的排序和命名模式。提供一组重载方法,这组重载方法带有递增数目的参数,以使开发人员可以指定想要的级别的信息,这种情况很常见。您指定的参数越多,开发人员就可指定得越详细。
e. 如果必须提供重写方法的能力,请仅使最完整的重载是虚拟的并根据它来定义其他操作。
// 下面具体解释一下这种模式,只有最后一个方法(参数最完整的方法)是虚方法,在继承了这个类的子类中只要重写(override)这个方法就行了。
public class SampleClass
{
   private string myString;
   public MyClass(string str)
   {
      this.myString = str;
   }
   public int IndexOf(string s)
   {
      return IndexOf (s, 0);
   }
   public int IndexOf(string s, int startIndex)
   {
      return IndexOf(s, startIndex, myString.Length - startIndex );
   }
   public virtual int IndexOf(string s, int startIndex, int count)
   {
      return myString.IndexOf(s, startIndex, count);
   }
}
===============================================================================================
Java的重写和重载机制
Java的重写和重载是两种在Java中经常提到的两组概念,它们在各个方面都有着很大的不同,本文主要在此做一个归纳总结。
Java的多态机制
++++++++++++++++++
+ Java的重写机制 +
++++++++++++++++++
即重写,重写主要用于子类和父类之间,在父类中定义了一个方法,同时在子类中对这个方法进行重写,实现子类行为的特殊化,例如:
class Animal{
  void eat(){ 
      System.out.print("animal eat");
   }
   }
 class Tiger extends Animal{
void eat()
{
System.out.print("Tiget eat");
}
}
子类中的eat方法即对父类的eat方法实现了重写,重写最常见的例子就是下面的声明:
 Animal some=new Tiger();
关于重写,遵循以下的规则:
 (1)重写方法必须和被重写方法具有相同的参数列表,返回类型必须和被重写方法的返回类型相同或者是返回类型的子类型。
 (2)重写方法的访问控制修饰符不能比被重写方法更严格(比如一个在父类中声明为public的方法重写成一个protected的方法)。
 (3)只有实例方法才能被重写,超类中的final方法不能被重写。
 (4)重写方法不能抛出新的检查异常,或者是抛出比被重写方法声明的检查异常更广泛的检查异常。
 (5)注意一种特殊情况:如果超类的方法版本中声明了检查异常,但重写的子类方法中没有声明,这时如果使用多态的方式进行调用,那么编译器认为你调用的是声明了异常的方法。
 (6)尽管多态是在编译时确定对象的类型,但在编译时,还是根据父类的方法声明进行程序检查。因此,如果子类中定义的方法,在父类中没有定义,则会出项编译错误。
++++++++++++++++++
+ Java的重载机制 +
++++++++++++++++++

    重载的实质:在一个类中使用签名相同的多个方法。
    按照范围,可以将重载分为在一个类中重载,和在子类和父类中重载。现分别解释如下:
    1.在一个类中定义多个具有相同签名的方法,这些方法必须具有不同的参数列表,比如一个类的构造函数。
    2.在父类和子类中,子类由于继承而拥有了父类的某些方法,此时在子类再定义具有相同签名的方法(必须具有不同的参数列表),这个地方很容易和重写相混淆,因此千万注意。
重载的规则主要记住亮点:
    一是方法的参数列表必须改变,包括参数的类型,参数的个数多少,参数顺序。
    二是重载对返回类型,访问修饰符,异常声明没有任何限制,可以作任意的修改。
    实质上,重载只是创建了一个方法而已,特殊的地方在于方法的名字。
注意下面的一种情况:(重写和重载的混合)
class UseAnimal{
     void doStuff(Animal sa){}
     void doStuff(Tiger sa){}
     public static void main(String[] args){
UseAnimal ua=new UseAnimal();
Animal an=new Tiger();
ua.duStuff(an);
}
}
此时,调用的方法doStuff的Animal版本,因为调用重载方法是在编译时决定的,an的声明类型是Animal。所以调用Animal版本。
始终注意一点:重载的判断始终是在编译时决定。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

一、重写(override)

override是重写(覆盖)了一个方法,以实现不同的功能。一般是用于子类在继承父类时,重写(重新实现)父类中的方法。

重写(覆盖)的规则:

   1、重写方法的参数列表必须完全与被重写的方法的相同,否则不能称其为重写而是重载.

   2、重写方法的访问修饰符一定要大于被重写方法的访问修饰符(public>protected>default>private)。

   3、重写的方法的返回值必须和被重写的方法的返回一致;

   4、重写的方法所抛出的异常必须和被重写方法的所抛出的异常一致,或者是其子类;

   5、被重写的方法不能为private,否则在其子类中只是新定义了一个方法,并没s有对其进行重写。

   6、静态方法不能被重写为非静态的方法(会编译出错)。

override就是子类将父类的方法重新实现了一遍。
new就是说这个方法就是子类自己的,跟父类没有任何继承关系关系,仅仅是重名

public class A
{
public virtual string Function()
{
return "1";
}
}
public class B : A
{
public override string Function()
{
return "2";
}
}
public class C : A
{
public new string Function()
{
return "3";
}
}

public class JustForTest
{
public void DoTest()
{
B b = new B();
C c = new C();

Console.WriteLine(b.Function());
Console.WriteLine(c.Function());
Console.WriteLine((b as A).Function());//这两个就体现出来了,B还是调用自己,返回2
Console.WriteLine((c as A).Function());//C调用的是基类,返回0
}
}


复制代码
override就是子类将父类的方法重新实现了一遍。
new就是说这个方法就是子类自己的,跟父类没有任何继承关系关系,仅仅是重名

public class A
{
public virtual string Function()
{
return "1";
}
}
public class B : A
{
public override string Function()
{
return "2";
}
}
public class C : A
{
public new string Function()
{
return "3";
}
}

public class JustForTest
{
public void DoTest()
{
B b = new B();
C c = new C();

Console.WriteLine(b.Function());
Console.WriteLine(c.Function());
Console.WriteLine((b as A).Function());//这两个就体现出来了,B还是调用自己,返回2
Console.WriteLine((c as A).Function());//C调用的是基类,返回0
}
}
复制代码

 二、overload是重载,一般是用于在一个类内实现若干重载的方法,这些方法的名称相同而参数形式不同。

重载的规则:

   1、在使用重载时只能通过相同的方法名、不同的参数形式实现。不同的参数类型可以是不同的参数类型,不同的参数个数,不同的参数顺序(参数类型必须不一样);

   2、不能通过访问权限、返回类型、抛出的异常进行重载;

   3、方法的异常类型和数目不会对重载造成影响;

多态的概念比较复杂,有多种意义的多态,一个有趣但不严谨的说法是:继承是子类使用父类的方法,而多态则是父类使用子类的方法。

一般,我们使用多态是为了避免在父类里大量重载引起代码臃肿且难于维护。

举个例子:

public class Shape

{

public static void main(String[] args){

Triangle tri = new Triangle();

System.out.println("Triangle is a type of shape? " + tri.isShape());// 继承

Shape shape = new Triangle();

System.out.println("My shape has " + shape.getSides() + " sides."); // 多态

Rectangle Rec = new Rectangle();

Shape shape2 = Rec;

System.out.println("My shape has " + shape2.getSides(Rec) + " sides."); //重载

}

public boolean isShape(){

return true;

}

public int getSides(){

return 0 ;

}

public int getSides(Triangle tri){ //重载

return 3 ;

}

public int getSides(Rectangle rec){ //重载

return 4 ;

}

}

class Triangle extends Shape

{

public int getSides() { //重写,实现多态

return 3;

}

}

class Rectangle extends Shape

{

public int getSides(int i) { //重载

return i;

}

}


复制代码
public class Shape

{

public static void main(String[] args){

Triangle tri = new Triangle();

System.out.println("Triangle is a type of shape? " + tri.isShape());// 继承

Shape shape = new Triangle();

System.out.println("My shape has " + shape.getSides() + " sides."); // 多态

Rectangle Rec = new Rectangle();

Shape shape2 = Rec;

System.out.println("My shape has " + shape2.getSides(Rec) + " sides."); //重载

}

public boolean isShape(){

return true;

}

public int getSides(){

return 0 ;

}

public int getSides(Triangle tri){ //重载

return 3 ;

}

public int getSides(Rectangle rec){ //重载

return 4 ;

}

}

class Triangle extends Shape

{

public int getSides() { //重写,实现多态

return 3;

}

}

class Rectangle extends Shape

{

public int getSides(int i) { //重载

return i;

}

}
复制代码

注意Triangle类的方法是重写,而Rectangle类的方法是重载。对两者比较,可以发现多态对重载的优点:

如果用重载,则在父类里要对应每一个子类都重载一个取得边数的方法;

如果用多态,则父类只提供取得边数的接口,至于取得哪个形状的边数,怎样取得,在子类里各自实现(重写)。

posted @ 2015-12-24 14:07  情难舍,人难留  阅读(260)  评论(0编辑  收藏  举报