• OOP 面向对象


    一、面向过程

    我们是怎么思考和解决上面的问题的呢?

    答案是:我们自己的思维一直按照步骤来处理这个问题,这是我们常规思维,这就是所谓的面向过程POP编程


    二、面向过程POP为什么转换为面向对象OOP

    面向过程想的思想步骤越多,变化越多,是无法掌控的,所以有时候非常复杂,就比如我们拿起来手机玩游戏如果按照POP编程则代码如下:

    复制代码
    namespace OOP
    {
        /// <summary>
        /// OOP 面向对象编程 Object Oriented Programming
        /// </summary>
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("我要玩手机游戏了");
                Console.WriteLine("手机开机");
                Console.WriteLine("打开游戏");
                Console.WriteLine("正在打游戏");
                Console.WriteLine("游戏结束");
            }
        }
    }
    复制代码

    但是出现不同手机,不同的玩法,不同的游戏,那么又要重新写类似的东西,所以面向过程虽然更更符合人的思考方式,但是及其不方便扩展管理,不能够重复使用,尤其是项目复杂的情况下,会使编程不好维护

     但是怎么从POP转换为OOP呢?

    我们通过手机玩游戏,可以转换一下思想,我们把对象进行分析,可以把手机,玩家,游戏分别定义为一个对象,可以参考如下:

    1.玩家类

    /// <summary>
        /// 玩家类
        /// </summary>
        public class Player
        {
            /// <summary>
            /// 玩家Id
            /// </summary>
            public int Id { get; set; }
            /// <summary>
            /// 玩家名字
            /// </summary>
            public string Name { get; set; }
    
            /// <summary>
            /// 玩手机方法
            /// </summary>
            /// <param name="phone"></param>
            public void PayerPhone(Phone phone)
            {
                //玩手机需要先开机
                phone.Open();
                //玩手机游戏
                phone.PlayGame();
            }
        }

    2.手机类

    /// <summary>
        /// 手机类
        /// </summary>
        public class Phone
        {
            /// <summary>
            /// 手机Id
            /// </summary>
            public int Id { set; get; }
            /// <summary>
            /// 手机Name
            /// </summary>
            public string Name { set; get; }
    
            public void PlayGame()
            {
                Game game = new Game();
                game.Start();
                game.Paly();
                game.Over();
            }
    
            /// <summary>
            /// 手机开机
            /// </summary>
            public void Open()
            {
                Console.WriteLine($"{this.GetType().Name}手机开机");
            }
            /// <summary>
            /// 手机关机
            /// </summary>
            public void Close()
            {
                Console.WriteLine($"{this.GetType().Name}手机关机");
            }
        }

    3.游戏类

    /// <summary>
        /// 游戏类
        /// </summary>
        public class Game
        {
            /// <summary>
            /// 开始
            /// </summary>
            public void Start()
            {
                Console.WriteLine($"{this.GetType().Name}游戏开始");
            }
            /// <summary>
            /// 正在进行
            /// </summary>
            public void Paly()
            {
                Console.WriteLine($"{this.GetType().Name}玩游戏");
            }
            /// <summary>
            /// 结束
            /// </summary>
            public void Over()
            {
                Console.WriteLine($"{this.GetType().Name}游戏结束");
            }
        }

    4.代码调用

    复制代码
     /// <summary>
        /// OOP 面向对象编程 Object Oriented Programming
        /// </summary>
        class Program
        {
            static void Main(string[] args)
            {
                //实例化一个玩家
                Player player = new Player()
                {
                    Id = 1,
                    Name="小明"
                };
    
                //小明想玩手机,首先得需要一部手机
                Phone phone = new Phone() {
                    Id = 1,
                    Name = "努比亚"
                };
    
                //小明开始玩手手机
                player.PayerPhone(phone);
            }
        }
    复制代码

    我们按照对象划分,就是所谓得万物皆对象,然后我们把对象定义好封装好,然后把对象属性和动作都归结一起,这就所谓得画格子,每个格子自成体系,内部任意改动不会影响到别人,然后每个格子之间相互交互!虽然我们使思路更加复杂化,但是以后极其容易扩展。

    总的来说面向对象就是把以前按照步骤考虑得然后划为对象,然后对象之间交互组成宫嗯那个,功能与宫嗯那个之间组成系统,系统与系统之间组成平台,比如:一块块砖砌成墙,然后墙与墙之间组成房间,房间与房间之间组成一个大厦

    三、面向对象的好处,特点【封装,继承,多态】

    1.封装的好处

      A:最主要的好处是:隔离,即是外部不用关系内部怎么实现,只要接口不变,内部可以随意扩展

      B:安全 private protect等数据结构,只能通过公开方法来访问,而不能随意修改致于保证数据的安全

      C:降低耦合,提高重要性,经理隐藏更多的东西

    2.继承的好处:就是为了代码重用,通过继承然后子类拥有父类的一切属性和行为,但只能单继承;重载(参数不一致,跟返回没有任何关系)

    3.多态:意味着有多重形式。在面向对象编程范式中,堕胎往往表现为“一个接口,多个功能”。

    4.多态的表现分为以下几种

      A:多态性可以是静态或者动态的,在静态多态中,函数响应是在编译时发生。在动态多态中,函数的响应是在运行时发生的。

      B:接口多态

      C:继承多态

    下面的代码能够体现出来封装、继承、多态

    复制代码
        /// <summary>
        /// 父类
        /// </summary>
        public abstract class ParentClass
        {
    
            public ParentClass()
            {
                Console.WriteLine($"(ParentClass)无参构造函数");
            }
    
            public void CommonMethod()
            {
                Console.WriteLine($"(ParentClass)父类普通方法");
            }
    
            public virtual void VirturalMethod()
            {
                Console.WriteLine($"(ParentClass)父类VirturalMethod()");
            }
            public virtual void VirturalMethod(int id)
            {
                Console.WriteLine($"(ParentClass)VirturalMethod(int id)");
            }
    
            public abstract void AbstractMethod();
        }
    
        //子类
        public class ChildClass : ParentClass
        {
            /// <summary>
            /// 实例化子类的时候,是先完成父类的实例化
            /// </summary>
            public ChildClass()
            {
                Console.WriteLine($"(ChildClass)无参构造函数");
            }
            /// <summary>
            /// new 隐藏基类方法,new 加不加一样的效果
            /// </summary>
            public new void CommonMethod()
            {
                Console.WriteLine($"(ChildClass)普通方法");
            }
    
            public override void VirturalMethod()
            {
                Console.WriteLine($"(ChildClass)VirturalMethod");
                //base.VirturalMethod(); //调用的父类的方法
            }
    
            public sealed override void AbstractMethod()
            {
                Console.WriteLine("(ChildClass)子类抽象方法");
            }
        }
    
        public class GrandClass : ChildClass
        {
            /// <summary>
            /// 可以重复覆写,如果不喜欢被重写,可以添加一个sealed
            /// </summary>
            //public override void AbstractMethod()
            //{
            //    throw new NotImplementedException();
            //}
            public override void VirturalMethod()
            {
                base.VirturalMethod(); //调用的父类的方法
            }
    
            public override void VirturalMethod(int i)
            {
                base.VirturalMethod(i); //调用的父类的方法
            }
        }
    复制代码

    然后再调用的时候会出现以下结果

    复制代码
    static void Main(string[] args)
    {
        ParentClass parentClass = new ChildClass();
        parentClass.CommonMethod(); //调用的父类的方法 普通方法由编译时决定-能够提高效率(由声明时决定)
        parentClass.VirturalMethod(); //调用的子类方法  虚方法由运行时决定的-多态灵活 (虚方法既可以覆写,也可以不覆写)
        parentClass.AbstractMethod(); //调用的子类的方法
    
        ChildClass childClass = new GrandClass();
        //VirturalMethod(int i) 里面有一句 base.VirturalMethod(int i) 
        //为什么显示 (ParentClass)VirturalMethod(int id)
        //原因是父类 ChildClass 没有重写ParentClass 的 VirturalMethod(int i)方法
        childClass.VirturalMethod(1);
    
        Console.ReadLine();
    }
    复制代码

    四、说下抽象类和抽象接口的区别

    1.抽象类和接口都不能直接被实例化。要是梨花,涉及到多态。抽象类要实例化,抽象类定义的变量必须指定一个子类变量,这个子类继承并实现了抽象类的所有抽象方法。接口要实例化,接口定义的变量必须只想一个子类变量,这个子类变量继承并实现接口的所有方法。

    2.抽象要被子类继承,接口要被子类实现。

    3.接口里只能对方法进行声明,抽象里既可以对方法进行声明也,又可以实现。

    4.抽象类里面的抽象方法被子类实现,如果子类不能全部实现,子类必须也是抽象类。接口里面的方法必须被子类实现,如果子类不能全部实现,子类必须是抽象类

    5.接口里面的方法不能具体的实现,这说明接口是设计的结果,而抽象类是重构的结果。

    6.抽象类里面可以没有抽象方法,如果一个类里面有抽象方法,那么这个类一定是抽象类。

    7.抽象类中的抽象方法都要被实现,所以抽象方法不能是静态的static,也不能是私有的private。

    8.接口可以继承接口,甚至可以击沉多个接口;类可以实现多个接口,只能继承一个类。

    9.抽象类主要用来抽象类别,接口主要用来抽象方法功能。关注事务的本质,用抽象类;关注一种操作,用接口

    接口可以定义一下内容

    复制代码
    /// <summary>
    /// 接口一般以大写I开头
    /// </summary>
    public interface IExtend
    {
        /// <summary>
        /// 属性可以,字段不行
        /// </summary>
        int Tag { set; get; }
    
        /// <summary>
        /// 方法
        /// </summary>
        void Play();
    
        //string Remark = null; //不能声明
        //class Test { }   //不能声明
        //Delegate void NoAction(); //不能声明
    
        /// <summary>
        /// 索引器
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        int this[int i]
        {
            get;
        }
        /// <summary>
        /// 事件
        /// </summary>
        event Action DoNothindHandler;
    }
    复制代码

    五、如何选择抽象类和接口的区别

    1:抽象类必须是一个父类,然后再方法不同的时候使用抽象实现,主要是为了代码重用 is a,所以抽象类可以说成是父类+约束,而且是单继承
    2:接口:仅仅是为了约束,告诉实现者一定要有某个功能 can do

    所以如果需要约束,一般选择接口,因为接口可以多实现并且多继承,除非项目中有代码需要重用,这样可以选择抽象类

    但是目前的大部分项目会选择基类和接口联合使用,比如有通用的属性等使用基类来创建,如果需要约束功能的话一般使用接口来约束,所以接口和抽象类可以相辅相成!

  • 相关阅读:
    Java之基础(1)
    Java之架构(0)
    Android Exception 11(baidumapsdk(15405): Authentication Error errorcode: 102 uid)
    Android Exception 10(server)' ~ Channel is unrecoverably broken and will be disposed!)
    IOS Exception 1(libc++abi.dylib: terminating with uncaught exception of type NSException)
    Android Exception 9(requestFeature() must be called before adding content)
    Android Exception 8(Couldn't read row 0, col -1 from CursorWindow)
    简洁的BP及RBF神经网络代码
    Android实现一键获取课程成绩dome
    hdu 5371 Hotaru&#39;s problem【manacher】
  • 原文地址:https://www.cnblogs.com/IT-Ramon/p/12061021.html
Copyright © 2020-2023  润新知