代码改变世界

不要在对抽象类接口abstract virtual什么的混淆不清了

2015-04-15 07:36  FelixShen  阅读(951)  评论(0编辑  收藏  举报

(最近带一个新手入门 讲这边老费力了。)

接口和抽象类不过都是类的抽象罢了,这是他们的本质,只不过人们的思维角度不同而已,一个偏向为行为契约上的抽象(接口) 一个更像大自然中的繁衍关系(抽象类)。

直接上代码:

class 抽象类
    {
        public static void Main(string[] args)
        {
            ChinesePerson c = new ChinesePerson("xx", 23);
            c.Run();
            c.Speak();
            Console.WriteLine(c.Name);
            Console.WriteLine(c.Age);
            Console.WriteLine(c.Hobby);
            Console.WriteLine("--------");
            c.fight();
            JiangSuPerson j = new JiangSuPerson();
            j.Name = "xiaomao";
            j.Age = 24;
            j.Run();
            j.Speak();
            j.fight();
            j.sing();
            Console.WriteLine(j.Name);
            Console.WriteLine(j.Age);
            Console.WriteLine(j.Hobby);
            Console.WriteLine("----------");
            HenanPerson h = new HenanPerson();
            h.Name = "linyi";
            h.Speak();
            h.fight();
            h.sing();
            Console.ReadKey();
        }
    }

    public interface IRun
    {
        void Run();
    }

  public abstract class Person : IRun
    {
        private string name;
        private int age;
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        public int Age
        {
            get { return age; }
            set { age = value; }
        }
        public abstract string Hobby { get; set; }
        public Person(string name, int age)
        {
            this.Name = name;
            this.Age = age;
        }
        public Person()
        { }
        public abstract void Speak();
        public void Run()
        {
            Console.WriteLine("Running ~~");
        }
        //能够被子类重写的 只有 abstract 或virtual修饰的,
        //不同在于,abstract一定要被重写,而virtual则是可以被重写 但不一定非要重写,还有就是virtual要有方法体。
        public virtual void fight()
        {
            Console.WriteLine("fighting");
        }
    }
    public class ChinesePerson : Person
    {

        public ChinesePerson(string name, int age)
            : base(name, age)
        {
            this.Name = name;
            this.Age = age;
        }
        public ChinesePerson()
        {
        }
        public override void Speak()
        {
            Console.WriteLine("中国人说中文");
        }

        public override string Hobby
        {
            get
            {
                return "shopping";
            }
            set
            {
            }
        }
        public override void fight()
        {
            base.fight();
            Console.WriteLine("chinese gongfu fighting");
        }
        public virtual void sing()
        {
            Console.WriteLine("用中文唱歌");
        }
    }

 //继承自中国人,但是没有任何重写
    public class JiangSuPerson : ChinesePerson
    {

    }
    public class HenanPerson : ChinesePerson
    {
        public override void Speak()
        {
            Console.WriteLine("河南人说河南方言");
        }
        public override void sing()
        {
            Console.WriteLine("用河南话唱歌");
        }
    }

 

总结一下:抽象类 和接口都是类的抽象,接口更关注从行为方面来抽象,而在语法上 接口的内容必须都是没有实现的,完全等待后面的类来实现的
而在这一点上,抽象类则像是一个没有完全实现的类,他想所有普通类一样,可以拥有字段,属性,以及方法,这些都是可以有具体实现体的,
但就这样的话,他和普通类的差别只在于他不可以通过new实例化,而他的真正不同在于 他应该有abstract修饰的部分,这部分没有具体实现,必须由
由后面的实现类来具体实现。
而virtual关键字本不该属于这里的讨论范畴,他修饰的方法和普通方法几乎一样,都是有着方法体的,但是被virtual修饰的可以被子类重写。

再举个例子模拟下mvc的控制器模块

 //大致模拟了MVC框架中的控制器模块的思想
    class 抽象类二
    {
        public static void Main(string[] args)
        {
            IController ic;
            ic = new HomeController();
            ic.Execute();
            Console.ReadKey();
        }
    }

    public interface IController
    {
        void Execute();
    }

    public abstract class ControllerBase : IController
    {
        //可以选择性的重写这整个方法,而不按照所期望的分步骤
        public virtual void Execute()
        {
            Console.WriteLine("doing some unimporting things");
            ExecuteCore();
        }
        //这个方法则必须实现
        public abstract void ExecuteCore();
    }
    public abstract class Controller : ControllerBase
    {
        public override void ExecuteCore()
        {
            Console.WriteLine("doing some importing things");
        }
        
        //public override void Execute()
        //{
        //    Console.WriteLine("doing the whole things");
        //}
    }
    public class HomeController : Controller
    {

    }