重写、重载、继承、多态

一、 重写
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;
        }
    }
}


多态对重载的优点:如果用重载,则在父类里要对应每一个子类都重载一个取得边数的方法;如果用多态,则父类只提供取得边数的接口,至于取得哪个形状的边数,怎样取得,在子类里各自实现(重写)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值