zoukankan      html  css  js  c++  java
  • 实现继承+接口继承+虚方法+隐藏方法+this/base+抽象类+密封类/方法+修饰符

    概念:

    在上一节课中学习了如何定义类,用类当做模板来声明我们的数据。

    很多类中有相似的数据,比如在一个游戏中,有Boss类,小怪类Enemy,这些类他们有很多相同的属性,也有不同的,这个时候我们可以使用继承来让这两个类继承自同一个类。

     

    分类:

    实现继承: 表示一个类型派生于一个基类型,它拥有该基类型的所有成员字段和函数。 在实现继承中,派生类型采用基类型的每个函数的实现代码,除非在派生类型的定义中指定重写某个函数的实现代码。 在需要给现有的类型添加功能,或许多相关的类型共享一组重要的公共功能时,这种类型的继承非常有用。

    接口继承: 表示一个类型只继承了函数的签名,没有继承任何实现代码。 在需要指定该类型具有某些可用的特性时,最好使用这种类型的继承。

    多重继承:

    C#不支持多重实现继承。 而 C#允许类型派生自多个接 口— — 多重接口继承。 这说明,C#类可以派生自另一个类和任意多个接口。更准确地说, System.Object 是一个公共的基类,所 以每个 C#(除了Object类之外)都有一个基类,还可以有任意多个基接 口。

    实现继承:

    如果要声明派生自另一个类的一个类,就可以使用下面的语法:
    class MyDerivedClass : MyBaseclass
    {
        // functions and data members here
    }
    如果类(或 结构)也 派生 自接 口,则用逗号分隔列表中的基类和接 口:
    public class MyDerivedClass: MyBaseClass , IInterface1 , IInterface2
    {
    // etc.
    }

    接口继承:

    namespace _012_定义和实现接口 {
        interface IA //不能有字段,方法不能被实现
        {
            void Method1();
        }
    }
    
    namespace _012_定义和实现接口 {
        interface IB:IA
        {
            void Method2();
        }
    }
    
    namespace _012_定义和实现接口 {
        interface IFly
        {
            void Fly();
            void MethodA();
        }
    }
    //继承了接口就要实现继承的接口中的所有方法,包括接口的父接口中的方法
    namespace _012_定义和实现接口 {
        class Bird :IFly,IB{
            public void Fly()
            {
                
            }
    
            public void MethodA()
            {
                
            }
    
            public void Method1()
            {
                
            }
    
            public void Method2()
            {
                
            }
        }
    }

    虚方法:

    把一个基类函数声明为virtual,就可以在任何派生类中重写该函数:
        class MyBaseClass{
            public virtual string VirtualMethod(){
                return "Method is called in base class";
            }
        }
    在派生类中重写另外一个函数时,要使用override关键字显示声明
        class MyDerivedClass:MyBaseClass{    
            public override string VirtualMethod(){
                return "Method is called in derivedclass.";
            }
        }
    我们在子类里面重写虚函数之后,子类对象不管在哪里调用都是调用重写之后的方法,可以不重写,不重写就调用父类的方法,将子类对象赋给父类对象也会调用子类中重写的方法

    隐藏方法(密封方法):

    如果签名相同的方法在基类和派生类中都进行了声明,但是该方法没有分别声明为virtual和override,派生类就会隐藏基类方法。(要使用new关键字进行声明)
    基类
    class MyBaseClass{
        public int MyMethod(){
        }
    }
    派生类(在派生类中把基类同名的方法隐藏掉了)
    class MyDerivedClass :MyBaseClass{
        public new void MyMethod()   //有没有new都可以,只是表示是隐藏方法,但是父类的方法还是存在的,重写的话父类的方法在子类中是不存在了    
    { } }

    Enemy enemy;
    enemy = new Boss();//父类声明的对象,可以使用子类去构造 子类声明的对象不可以使用父类构造
    //enemy虽然使用父类进行了声明,但是使用了子类构造,所以本质上是一个子类类型的,我们可以强制类型转换转换成子类类型
    Boss boss = (Boss)enemy;
    boss.Attack();

     

    Enemy enemy = new Enemy();
    Boss boss =(Boss) enemy;//一个对象是什么类型的 主要看它是通过什么构造的 这里enemy使用了父类的构造函数,所以只有父类中的字段和方法, 不能被强制转换成子类

    
    

    Enemy boss = new Boss();
    boss.Move();//隐藏方法: 如果使用子类声明的对象,调用隐藏方法会调用子类的,如果使用父类声明对象,那么就会调用父类中的隐藏方法

    this和base关键字:

    this可以访问当前类中定义的字段,属性和方法,有没有this都可以访问,有this可以让IDE-VS编译器给出提示,另外当方法的参数跟字段重名的时候,使用this可以表明访问的是类中的字段

    base可以调用父类中的公有方法和字段,有没有base都可以访问,但是加上base.IED工具会给出提示,把所有可以调用的字段和方法罗列出来方便选择

    使用base关键字调用父类构造函数的语法如下:
    子类构造函数:base(参数列表)
    使用base关键字调用父类方法的语法如下:
    base.父类方法();
    using System ; class Teacher//老师类 { public Teacher()//构造函数1 { Console.WriteLine ("我是一位教师。"); } public Teacher(string str)//构造函数2 { Console.WriteLine ("老师,"+str); } public void OutPut()//自定义方法 { Console.WriteLine ("输出方法"); } private string name; public string Name//属性 { get{return this.name;} set{this.name=value;} } public void getName() { Console.WriteLine ("我的名字是"+name); } } class Jack:Teacher { static string hello="你好"; public Jack():base(hello)//子类的构造函数继承的为父类第二个构造函数,注意写法 { } public void myOutPut()//自定义函数 { base.OutPut ();//引用父类的函数 } public string myName//自定义属性 { get{return base.Name ;} set{base.Name ="王"+value;} } } class Test { static void Main() { Jack j=new Jack ();//输出“老师,你好” j.myOutPut ();//输出"输出方法" j.myName ="猫骨"; j.getName ();//输出“王猫骨” } } 注意:base()调用父类构造函数时,不需要再次指定参数的类型,因为在子类中已经定义了这些参数,在base()中只需指定变量名即可,参数的类型必须和父类中的一致。

    抽象类:

    C#允许把类和函数声明为 abstract。 抽象类不能实例化,抽象类可以包含普通函数和抽象函数,抽象函数就是只有函数定义没有函数体。 显然,抽象函数本身也是虚拟的Virtual(只有函数定义,没有函数体实现)。
    类是一个模板,那么抽象类就是一个不完整的模板,我们不能使用不完整的模板去构造对象。,但是可以声明对象
      abstract class Bird//一个抽象类 就是一个不完整的模板
        {
            private float speed;
    
            public void Eat()
            {
                
            }
    
            public abstract void Fly();//抽象方法,没有实体
        }
    
     class Crow:Bird {//我们继承了一个抽象类的时候,必须去实现抽象方法
            public override void Fly()
            {
                Console.WriteLine("乌鸦在飞行");
            }
        }

    密封类和密封方法:

    C#允许把类和方法声明为 sealed对于类 ,这表示不能继承该类;对于方法表示不能重写该方法。
    sealed FinalClass
    {
    // etc
    }
    什么时候使用 密封类和密封方法?
      防止重写某些类导致代码混乱,在重写的方法override前加sealed
      商业原因

    派生类的构造函数:

    1,在子类中调用父类的默认构造函数(无参)(会先调用父类的,然后是子类的)
        public class MyDerivedClass{
            public MyDerivedClass():base(){
                //do something
            }
        }
        在这里 :base()可以直接不写,因为默认会调用父类中的默认构造函数 
    2,调用有参数的构造函数
        public class MyDerivedClass{
            public MyDerivedClass(string name):base(name){
                //do something
            }
        }

    修饰符:

    修饰符,用来类型或者成员的关键字。修饰符可以指定方法的可见性。

    public 和private修饰字段和方法的时候,表示该字段或者方法能不能通过对象去访问:

    只有public的才可以通过对象访问

    private(私有的)只能在类模板内部访问。

    protected 保护的,当没有继承的时候,它的作用和private是一样的,当有继承的时候,protected表示可以被子类访问的字段或者方法

    类型的修饰符:

    public class ...

    class ...

    前者可以在别的项目下访问,后者不行

     

    其他修饰符:

    static可以修饰字段或者方法,修饰字段的时候,表示这个字段是静态的数据,叫做静态字段或者静态属性,修饰方法的时候,叫做静态方法,或者静态函数 使用static修饰的成员,只能通过类名访问 当我们构造对象的时候,对象中只包含了普通的字段,不包含静态字段

  • 相关阅读:
    java中的几种对象(PO,VO,DAO,BO,POJO)
    【转】Spring boot 打成jar包问题总结
    mac 上安装lua
    Mac下更新Vim到最新版本
    刘以鬯和香港文学
    权重随机算法的java实现
    MySQL具体解释(7)-----------MySQL线程池总结(一)
    IIS PHP 配置 问题总结
    HDU 3622 Bomb Game(2-sat)
    poj 2388 Who's in the Middle
  • 原文地址:https://www.cnblogs.com/dsh20134584/p/7384779.html
Copyright © 2011-2022 走看看