首页 > 技术文章 > C# 面向对象——多态

sxw117886 2016-07-06 18:18 原文

多态分三种:1.虚方法  

                 2.抽象类

                 3.接口

1、虚方法
1、将父类的方法标记为虚方法 ,使用关键字 virtual,这个函数可以被子类重新写一个遍。

如:

class Program
    {
        static void Main(string[] args)
        {
            Chinese cn1 = new Chinese("韩梅梅");
            Chinese cn2 = new Chinese("李雷");
            American a1 = new American("科比布莱恩特");
            American a2 = new American("奥尼尔");
            Person[] pers = { cn1, cn2,  a1, a2, };

            for (int i = 0; i < pers.Length; i++)
            {

                pers[i].SayHello();
            }
            Console.ReadKey();
        }
    }

    /// <summary>
    /// 父类——人类
    /// </summary>
    public class Person
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        public Person(string name)
        {
            this.Name = name;
        }
        public virtual void SayHello()
        {
            Console.WriteLine("我是人类");
        }

    }

    /// <summary>
    /// 子类——中国人
    /// </summary>
    public class Chinese : Person
    {
        public Chinese(string name)
            : base(name)
        {

        }

        public override void SayHello()
        {
            Console.WriteLine("我是中国人,我叫{0}", this.Name);
        }
    }
  
    /// <summary>
    /// 子类——美国人
    /// </summary>
    public class American : Person
    {
        public American(string name)
            : base(name)
        {

        }

        public override void SayHello()
        {
            Console.WriteLine("我叫{0},我是米国人", this.Name);
        }
    }
View Code

2、抽象类
当父类中的方法不知道如何去实现的时候,可以考虑将父类写成抽象类,将方法写成抽象方法。

class Program
    {
        static void Main(string[] args)
        {
            //狗狗会叫 猫咪会叫

            Animal a = new Cat();//new Dog();
            a.Bark();
            
            Console.ReadKey();
        }
    }

    /// <summary>
    /// 父类——动物
    /// </summary>
    public abstract class Animal
    {

        public virtual void T()
        {
            Console.WriteLine("动物有声明");
        }

        private int _age;

        public int Age
        {
            get { return _age; }
            set { _age = value; }
        }

        public Animal(int age)
        {
            this.Age = age;
        }
        public abstract void Bark();
        public abstract string Name
        {
            get;
            set;
        }

        public Animal()
        { 
            
        }
    }

    /// <summary>
    /// 子类——测试
    /// </summary>
    public abstract class Test : Animal
    { 
        
    }

    /// <summary>
    ///子类——狗
    /// </summary>
    public class Dog : Animal
    {
        public override void Bark()
        {
            Console.WriteLine("狗狗旺旺的叫");
        }

        public override string Name
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }
    }

    /// <summary>
    /// 子类——猫
    /// </summary>
    public class Cat : Animal
    {
        public override void Bark()
        {
            Console.WriteLine("猫咪喵喵的叫");
        }

        public override string Name
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }
    }
View Code

抽象类特点:

1).抽象成员必须标记为abstract,并且不能有任何实现。

public abstract class Animal
{

  public abstract void Bark();

}

2).抽象成员必须在抽象类中。
3).抽象类不能被实例化

4).子类继承抽象类后,必须把父类中的所有抽象成员都重写。

(除非子类也是一个抽象类,则可以不重写)
5).抽象成员的访问修饰符不能是private
6).在抽象类中可以包含实例成员。
并且抽象类的实例成员可以不被子类实现

7).抽象类是有构造函数的。虽然不能被实例化。


8)、如果父类的抽象方法中有参数,那么。继承这个抽象父类的子类在重写父类的方法的时候必须传入对应的参数。

如果抽象父类的抽象方法中有返回值,那么子类在重写这个抽象方法的时候 也必须要传入返回值。

3.接口

class Program
    {
        static void Main(string[] args)
        {
            IFlyable fly = new Bird();//new Person();
            fly.Fly();
            Console.ReadKey();
        }
    }
    public class Person:IFlyable
    {
        public void Fly()
        {
            Console.WriteLine("人类在飞");
        }
    }


    public class Student 
    {
        public void Fly()
        {
            Console.WriteLine("人类在飞");
        }
    }

    public class Bird : IFlyable
    {
        public void Fly()
        {
            Console.WriteLine("鸟在飞");
        }
    }

    public interface IFlyable
    {
        //不允许有访问修饰符 默认为public
        //方法、自动属性
        void Fly();
    }



    public interface M1
    {
        void Test1();
    }

    public interface M2
    {
        void Test2();
    }

    public interface M3
    {
        void Test3();
    }


    public interface SupperInterface : M1, M2, M3
    { 
        
    }

    public class Car : SupperInterface
    {

        public void Test1()
        {
            throw new NotImplementedException();
        }

        public void Test2()
        {
            throw new NotImplementedException();
        }

        public void Test3()
        {
            throw new NotImplementedException();
        }
    }
View Code

接口是一种规范。
只要一个类继承了一个接口,这个类就必须实现这个接口中所有的成员

为了多态。 接口不能被实例化。
也就是说,接口不能new(不能创建对象)

接口中的成员不能加“访问修饰符”,接口中的成员访问修饰符为public,不能修改。


(默认为public) 接口中的成员不能有任何实现(“光说不做”,只是定义了一组未实现的成员)。


接口中只能有方法、属性、索引器、事件,不能有“字段”和构造函数。

接口与接口之间可以继承,并且可以多继承。

接口并不能去继承一个类,而类可以继承接口 (接口只能继承于接口,而类既可以继承接口,也可以继承类)

实现接口的子类必须实现该接口的全部成员。

一个类可以同时继承一个类并实现多个接口,如果一个子类同时继承了父类A,并实现了接口IA,那么语法上A必须写在IA的前面。


class MyClass:A,IA{},因为类是单继承的。


显示实现接口的目的:解决方法的重名问题
什么时候显示的去实现接口:
当继承的借口中的方法和参数一摸一样的时候,要是用显示的实现接口


当一个抽象类实现接口的时候,需要子类去实现接口。


======
如果父类中的方法有默认的实现,并且父类需要被实例化,这时可以考虑将父类定义成一个普通类,用虚方法来实现多态。

如果父类中的方法没有默认实现,父类也不需要被实例化,则可以将该类定义为抽象类。

 

推荐阅读