一、 重写
1.概念
是指重写基类的方法,在基类中的方法必须有修饰符virtual,而在子类的方法中必须指明override。
1. 在基类中:
public virtual void myMethod()
{
}
2.在子类中:
public override void myMethod()
{
}
重写以后,用基类对象和子类对象访问myMethod()方法,结果都是访问在子类中重新定义的方法,基类的方法相当于被覆盖掉了。
需要注意的地方有两点:
①.可以在子类中被重写的方法一定要被标记成virtual(虚拟), abstract(抽象), override(重写)标记为virtual 和abstract 的函数就是为了重写而创建的,标记为override的函数本身是由前两种函数重写而来的,所以它可以被重写也是顺理成章的了;
②.重写的函数必须在子类中出现,而且任何一个父类的函数在其一个子类中只能被重写一次。(这一点很好理解,当你要重写两次时,该子类中将定义两个返回类型,方法名称 和参数列表都相同的函数,这肯定是不可能的)。
2. 实例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OverrideExample
{
abstract class Animal
{
protected string _name;
//声明抽象属性
public abstract string Name
{
get;
}
//声明抽象方法
public abstract void Show();
//实现虚方法
public virtual void MakeVoice()
{
Console.WriteLine("All animals can make voice.");
}
//实现一般的方法
public void Sleep()
{
Console.WriteLine("All the animals need to sleep.");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OverrideExample
{
class Dog : Animal
{
public Dog()
{
}
public Dog(string name)
{
_name = name;
}
public override string Name
{
get
{
return _name;
}
}
public override void Show()
{
}
//基类方法
public virtual void FurColor()
{
Console.WriteLine("Performing base class fur color");
}
//用new关键字将虚方法隐藏
public new void MakeVoice()
{
//base.MakeVoice();//调用基类方法
Console.WriteLine(" I'am a dog,wang...wang...");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OverrideExample
{
class Duck : Animal
{
public Duck(string name)
{
this._name = name;
}
public override void Show()
{
}
//重写抽象属性
public override string Name
{
get
{
return _name;
}
}
//重写虚方法
public override void MakeVoice()
{
Console.WriteLine("I am a duck,ga....ga....");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OverrideExample
{
class Pomeranian : Dog
{
public Pomeranian()
{
}
//子类重写基类方法
public override void FurColor()
{
Console.WriteLine("Pomeranian's fur color is white.");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OverrideExample
{
class Program
{
static void Main(string[] args)
{
/*
*Duck重写了Makevoice(),只能实现子类中的方法
*Dog隐藏了Makevoice(),但是父类还可以调用它的代码
*/
Animal duck = new Duck("Duck");
duck.MakeVoice();//调用override重写后的虚方法
Animal dog = new Dog("Dog");
dog.MakeVoice();//直接调用基类虚方法(new 关键字方法隐藏)
Dog dog1 = new Dog("dog1");
dog1.MakeVoice();//调用new隐藏后的方法
}
}
}
二、 重载
1.概念
同一个类不可以有两个相同的方法(方法名、参数类型、参数个数和参数位置都 相同)。但可以有方法名相同,参数不同(参数类型、参数个数和参数位置不相同)的方法。这 种相同的方法名,参数不同的方法称为重载。用于在给定了参数列表和一组候选函数成员的情况下,选择一个最佳函数成员来实施调用。
1.方法名必须相同
2.参数列表必须不相同,与参数列表的顺序无关
3.返回值类型可以不相同
4.同一个类中
public void test(int x,int y){}
public void test(int x,ref int y){}
public void test(int x,int y,string a){}
3. 实例
class BattleRavage:Dog {
public BattleRavage():base("brDog")
{
}
//这只狗有计算的能力,实现重载功能
public string add()
{
return "I'm ready!";
}
public double add(double numberOne, double numberTwo)
{
return numberOne + numberTwo;
}
public double add(double numberOne, double numberTwo, double numberThree)
{
return numberOne + numberTwo + numberThree;
}
public new void Sleep()
{
Console.WriteLine("I don't need to go to");
}
}
//实现重载add()
BattleRavage brDog = new BattleRavage();
brDog.Sleep();//调用new方法
Console.WriteLine("这条狗能做算术,很厉害!");
string dogReady = brDog.add();
double result1 = brDog.add(2.2, 5.5);
double result2 = brDog.add(2, 4, 3);
Console.WriteLine(dogReady);
Console.WriteLine("2.2+5.5=" + result1.ToString());
Console.WriteLine("2+4+3=" + result2.ToString());
Console.WriteLine();
三、 继承
继承就是子类获得父类的成员和使用父类的方法。
C#中的继承符合下列规则:
1、继承是可传递的。如果C从B中派生,B又从A中派生,那么C不仅继承了B中声明的成员,同样也继承了A中的成员。Object 类作为所有类的基类。
2、派生类应当是对基类的扩展。派生类可以添加新的成员,但不能除去已经继承的成员的定义。
3、构造函数和析构函数不能被继承。除此以外的其它成员,不论对它们定义了怎样的访问方式,都能被继承。基类中成员的访问方式只能决定派生类能否访问它们。
4、派生类如果定义了与继承而来的成员同名的新成员,就可以覆盖已继承的成员。但这并不因为这派生类删除了这些成员,只是不能再访问这些成员。
5、类可以定义虚方法、虚属性以及虚索引指示器,它的派生类能够重载这些成员,从而实现类可以展示出多态性。
6、派生类只能从一个类中继承,可以通过接吕实现多重继承。
四、多态
1.概念
c#的多态性主要体现在类的继承上:
子类继承父类的时候,可能出现同名但方法定义不同的情况,
所以在子类中会将原方法覆盖,实现自身的要求.
网上看到一个有趣的说法是:继承是子类使用父类的方法,而多态则是父类使用子类的方法。
多态性具有两个截然不同的方面:
1.在运行时,在方法参数和集合或数组等位置,派生类的对象可以作为基类的对象处理。 发生此情况时,该对象的声明类型不再与运行时类型相同。
2.基类可以定义并实现虚方法,派生类可以重写这些方法,即派生类提供自己的定义和实现。 在运行时,客户端代码调用该方法,CLR 查找对象的运行时类型,并调用虚方法的重写方法。 因此,您可以在源代码中调用基类的方法,但执行该方法的派生类版本。
C#支持两种类型的多态性:
1.编译时的多态性
编译时的多态性是通过重载来实现的。对于非虚的成员来说,系统在编译时,根据传递的参数、返回的类型等信息决定实现何种操作。
2.运行时的多态性
运行时的多态性就是指直到系统运行时,才根据实际情况决定实现何种操作。C#中,运行时的多态性通过虚成员实现。
编译时的多态性为我们提供了运行速度快的特点,而运行时的多态性则带来了高度灵活和抽象的特点。
2.实例
public class Dog : Animals, IAction {
public Dog()
{
}
public Dog(string name)
{
_name = name;
}
public override string Name
{
get
{
return _name;
}
}
public virtual void FurColor(){
Console.WriteLine("Performing base class fur color");
}
}
class Pomeranian:Dog {
public Pomeranian()
{
}
public override void FurColor()
{
Console.WriteLine("Pomeranian's fur color is white.");
//base.FurColor();
}
}
class Labrador:Dog {
public Labrador()
{
}
public override void FurColor()
{
Console.WriteLine("Labrador's fur color is pale yellow.");
//base.FurColor();
}
}
class Husky:Dog {
public Husky()
{
}
public override void FurColor()
{
Console.WriteLine("Husky' fur color is black and white mixed color.");
base.FurColor();
}
}
class Program {
static void Main(string[] args)
{
//实现多态,调用基类的方法,但执行该方法的派生类版本
List<Dog> dogs = new List<Dog>();
dogs.Add(new Husky());
dogs.Add(new Labrador());
dogs.Add(new Pomeranian());
foreach (Dog s in dogs)
{
s.FurColor();
}
}
}
五、总结
1.多态、重写、重载和继承
多态性通过继承、重写、虚方法等来实现,重写就是在子类中写出和基类中不同的方法(该方法可以为virtual、abstract 或 override)实现(方法名,参数,返回值都一样),重载允许我们用相同的方法名实现不同的操作,继承则是子类获得父类的成员和使用父类的方法。
2.实例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace All
{
class Program
{
static void Main(string[] args)
{
//继承
Triangle tri = new Triangle();
Console.WriteLine("Triangle is a type of sharp? " + tri.isSharp());
//多态
Shape shape = new Triangle();
Console.WriteLine("My shape has " + shape.getSides() + " sides.");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace All
{
class Shape
{
public Boolean isSharp()
{
return true;
}
//重载
public virtual int getSides()
{
return 0;
}
public int getSides(Triangle tri)
{
return 3;
}
public int getSides(Rectangle rec)
{
return 4;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace All
{
class Triangle : Shape
{
//重写
public override int getSides()
{
return 3;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace All
{
class Rectangle : Shape
{
//重载
public int getSides(int i)
{
return i;
}
}
}
多态对重载的优点:如果用重载,则在父类里要对应每一个子类都重载一个取得边数的方法;如果用多态,则父类只提供取得边数的接口,至于取得哪个形状的边数,怎样取得,在子类里各自实现(重写)。
1.概念
是指重写基类的方法,在基类中的方法必须有修饰符virtual,而在子类的方法中必须指明override。
1. 在基类中:
public virtual void myMethod()
{
}
2.在子类中:
public override void myMethod()
{
}
重写以后,用基类对象和子类对象访问myMethod()方法,结果都是访问在子类中重新定义的方法,基类的方法相当于被覆盖掉了。
需要注意的地方有两点:
①.可以在子类中被重写的方法一定要被标记成virtual(虚拟), abstract(抽象), override(重写)标记为virtual 和abstract 的函数就是为了重写而创建的,标记为override的函数本身是由前两种函数重写而来的,所以它可以被重写也是顺理成章的了;
②.重写的函数必须在子类中出现,而且任何一个父类的函数在其一个子类中只能被重写一次。(这一点很好理解,当你要重写两次时,该子类中将定义两个返回类型,方法名称 和参数列表都相同的函数,这肯定是不可能的)。
2. 实例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OverrideExample
{
abstract class Animal
{
protected string _name;
//声明抽象属性
public abstract string Name
{
get;
}
//声明抽象方法
public abstract void Show();
//实现虚方法
public virtual void MakeVoice()
{
Console.WriteLine("All animals can make voice.");
}
//实现一般的方法
public void Sleep()
{
Console.WriteLine("All the animals need to sleep.");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OverrideExample
{
class Dog : Animal
{
public Dog()
{
}
public Dog(string name)
{
_name = name;
}
public override string Name
{
get
{
return _name;
}
}
public override void Show()
{
}
//基类方法
public virtual void FurColor()
{
Console.WriteLine("Performing base class fur color");
}
//用new关键字将虚方法隐藏
public new void MakeVoice()
{
//base.MakeVoice();//调用基类方法
Console.WriteLine(" I'am a dog,wang...wang...");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OverrideExample
{
class Duck : Animal
{
public Duck(string name)
{
this._name = name;
}
public override void Show()
{
}
//重写抽象属性
public override string Name
{
get
{
return _name;
}
}
//重写虚方法
public override void MakeVoice()
{
Console.WriteLine("I am a duck,ga....ga....");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OverrideExample
{
class Pomeranian : Dog
{
public Pomeranian()
{
}
//子类重写基类方法
public override void FurColor()
{
Console.WriteLine("Pomeranian's fur color is white.");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OverrideExample
{
class Program
{
static void Main(string[] args)
{
/*
*Duck重写了Makevoice(),只能实现子类中的方法
*Dog隐藏了Makevoice(),但是父类还可以调用它的代码
*/
Animal duck = new Duck("Duck");
duck.MakeVoice();//调用override重写后的虚方法
Animal dog = new Dog("Dog");
dog.MakeVoice();//直接调用基类虚方法(new 关键字方法隐藏)
Dog dog1 = new Dog("dog1");
dog1.MakeVoice();//调用new隐藏后的方法
}
}
}
二、 重载
1.概念
同一个类不可以有两个相同的方法(方法名、参数类型、参数个数和参数位置都 相同)。但可以有方法名相同,参数不同(参数类型、参数个数和参数位置不相同)的方法。这 种相同的方法名,参数不同的方法称为重载。用于在给定了参数列表和一组候选函数成员的情况下,选择一个最佳函数成员来实施调用。
1.方法名必须相同
2.参数列表必须不相同,与参数列表的顺序无关
3.返回值类型可以不相同
4.同一个类中
public void test(int x,int y){}
public void test(int x,ref int y){}
public void test(int x,int y,string a){}
3. 实例
class BattleRavage:Dog {
public BattleRavage():base("brDog")
{
}
//这只狗有计算的能力,实现重载功能
public string add()
{
return "I'm ready!";
}
public double add(double numberOne, double numberTwo)
{
return numberOne + numberTwo;
}
public double add(double numberOne, double numberTwo, double numberThree)
{
return numberOne + numberTwo + numberThree;
}
public new void Sleep()
{
Console.WriteLine("I don't need to go to");
}
}
//实现重载add()
BattleRavage brDog = new BattleRavage();
brDog.Sleep();//调用new方法
Console.WriteLine("这条狗能做算术,很厉害!");
string dogReady = brDog.add();
double result1 = brDog.add(2.2, 5.5);
double result2 = brDog.add(2, 4, 3);
Console.WriteLine(dogReady);
Console.WriteLine("2.2+5.5=" + result1.ToString());
Console.WriteLine("2+4+3=" + result2.ToString());
Console.WriteLine();
三、 继承
继承就是子类获得父类的成员和使用父类的方法。
C#中的继承符合下列规则:
1、继承是可传递的。如果C从B中派生,B又从A中派生,那么C不仅继承了B中声明的成员,同样也继承了A中的成员。Object 类作为所有类的基类。
2、派生类应当是对基类的扩展。派生类可以添加新的成员,但不能除去已经继承的成员的定义。
3、构造函数和析构函数不能被继承。除此以外的其它成员,不论对它们定义了怎样的访问方式,都能被继承。基类中成员的访问方式只能决定派生类能否访问它们。
4、派生类如果定义了与继承而来的成员同名的新成员,就可以覆盖已继承的成员。但这并不因为这派生类删除了这些成员,只是不能再访问这些成员。
5、类可以定义虚方法、虚属性以及虚索引指示器,它的派生类能够重载这些成员,从而实现类可以展示出多态性。
6、派生类只能从一个类中继承,可以通过接吕实现多重继承。
四、多态
1.概念
c#的多态性主要体现在类的继承上:
子类继承父类的时候,可能出现同名但方法定义不同的情况,
所以在子类中会将原方法覆盖,实现自身的要求.
网上看到一个有趣的说法是:继承是子类使用父类的方法,而多态则是父类使用子类的方法。
多态性具有两个截然不同的方面:
1.在运行时,在方法参数和集合或数组等位置,派生类的对象可以作为基类的对象处理。 发生此情况时,该对象的声明类型不再与运行时类型相同。
2.基类可以定义并实现虚方法,派生类可以重写这些方法,即派生类提供自己的定义和实现。 在运行时,客户端代码调用该方法,CLR 查找对象的运行时类型,并调用虚方法的重写方法。 因此,您可以在源代码中调用基类的方法,但执行该方法的派生类版本。
C#支持两种类型的多态性:
1.编译时的多态性
编译时的多态性是通过重载来实现的。对于非虚的成员来说,系统在编译时,根据传递的参数、返回的类型等信息决定实现何种操作。
2.运行时的多态性
运行时的多态性就是指直到系统运行时,才根据实际情况决定实现何种操作。C#中,运行时的多态性通过虚成员实现。
编译时的多态性为我们提供了运行速度快的特点,而运行时的多态性则带来了高度灵活和抽象的特点。
2.实例
public class Dog : Animals, IAction {
public Dog()
{
}
public Dog(string name)
{
_name = name;
}
public override string Name
{
get
{
return _name;
}
}
public virtual void FurColor(){
Console.WriteLine("Performing base class fur color");
}
}
class Pomeranian:Dog {
public Pomeranian()
{
}
public override void FurColor()
{
Console.WriteLine("Pomeranian's fur color is white.");
//base.FurColor();
}
}
class Labrador:Dog {
public Labrador()
{
}
public override void FurColor()
{
Console.WriteLine("Labrador's fur color is pale yellow.");
//base.FurColor();
}
}
class Husky:Dog {
public Husky()
{
}
public override void FurColor()
{
Console.WriteLine("Husky' fur color is black and white mixed color.");
base.FurColor();
}
}
class Program {
static void Main(string[] args)
{
//实现多态,调用基类的方法,但执行该方法的派生类版本
List<Dog> dogs = new List<Dog>();
dogs.Add(new Husky());
dogs.Add(new Labrador());
dogs.Add(new Pomeranian());
foreach (Dog s in dogs)
{
s.FurColor();
}
}
}
五、总结
1.多态、重写、重载和继承
多态性通过继承、重写、虚方法等来实现,重写就是在子类中写出和基类中不同的方法(该方法可以为virtual、abstract 或 override)实现(方法名,参数,返回值都一样),重载允许我们用相同的方法名实现不同的操作,继承则是子类获得父类的成员和使用父类的方法。
2.实例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace All
{
class Program
{
static void Main(string[] args)
{
//继承
Triangle tri = new Triangle();
Console.WriteLine("Triangle is a type of sharp? " + tri.isSharp());
//多态
Shape shape = new Triangle();
Console.WriteLine("My shape has " + shape.getSides() + " sides.");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace All
{
class Shape
{
public Boolean isSharp()
{
return true;
}
//重载
public virtual int getSides()
{
return 0;
}
public int getSides(Triangle tri)
{
return 3;
}
public int getSides(Rectangle rec)
{
return 4;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace All
{
class Triangle : Shape
{
//重写
public override int getSides()
{
return 3;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace All
{
class Rectangle : Shape
{
//重载
public int getSides(int i)
{
return i;
}
}
}
多态对重载的优点:如果用重载,则在父类里要对应每一个子类都重载一个取得边数的方法;如果用多态,则父类只提供取得边数的接口,至于取得哪个形状的边数,怎样取得,在子类里各自实现(重写)。