16.继承中的构造函数

16.面向对象-继承-继承中的构造函数


16.1 知识点

知识回顾

构造函数的作用

  • 实例化对象时调用的函数
  • 主要用来初始化成员变量
  • 每个类都会有一个默认的无参构造函数

构造函数的语法

访问修饰符 类名()
{
    // 构造函数体
}

构造函数的特点

  • 不写返回值
  • 函数名和类名相同
  • 访问修饰符根据需求而定,一般为public
  • 构造函数可以重载
  • 可以用this语法重用代码

构造函数的注意事项

  • 有参构造会顶掉默认的无参构造
  • 如果想保留无参构造,需要重载出来

构造函数的实例

class Test
{
    public int testI;
    public string testStr;

    public Test() { }

    public Test(int i)
    {
        this.testI = i;
    }

    public Test(int i, string str) : this(i)
    {
        this.testStr = str;
    }
}

继承中的构造函数

特点

  • 当申明一个子类对象时,先执行父类的构造函数,再执行子类的构造函数
  • 注意:
    • 父类的无参构造很重要
    • 子类可以通过base关键字代表父类调用父类构造

继承中构造函数的执行顺序

class语句块外 namespace语句块内

// 父类的父类的构造——>。。。父类构造——>。。。——>子类构造

//游戏对象类
class GameObject
{
    public GameObject()
    {
        Console.WriteLine("GameObject的构造函数");
    }
}

//玩家类
class Player : GameObject
{
    public Player()
    {
        Console.WriteLine("Player的构造函数");
    }
}

//主玩家类
class MainPlayer : Player
{
    public MainPlayer()
    {
        Console.WriteLine("MainPlayer的构造函数");
    }
}

主函数内

MainPlayer mainplayer = new MainPlayer();
//GameObject的构造函数
//Player的构造函数
//MainPlayer的构造函数

父类的无参构造函数的重要性

class语句块外 namespace语句块内

//父类
class Father
{
    //当父类无参构造函数被顶掉或者不存在的时候
    //子类会报错,因为Son son = new Son(); 会默认调用父类的无参构造函数
    //public Father() { }

    public Father(int i)
    {
        Console.WriteLine("Father的一个参数的构造");
    }
}

//子类

class Son : Father
{
    //子类内
    //通过base调用Father的一个参数的构造函数
    public Son(int i) : base(i)
    {
        Console.WriteLine("Son的一个参数的构造");
    }

    //通过this调用Son的一个参数的构造函数
    public Son(int i, string str) : this(i)
    {
        Console.WriteLine("Son的两个参数的构造");
    }
}

主函数内

//Son son = new Son();//报错,父类无参构造函数被顶掉或者不存在

通过base调用指定父类构造

子类内

//子类

class Son : Father
{
    //子类内

    //通过base调用Father的一个参数的构造函数
    public Son(int i) : base(i)
    {
        Console.WriteLine("Son的一个参数的构造");
    }

    //通过this调用Son的一个参数的构造函数
    public Son(int i, string str) : this(i)
    {
        Console.WriteLine("Son的两个参数的构造");
    }
}

主函数内

Son son = new Son(1, "123");
//Father的一个参数的构造
//Son的一个参数的构造
//Son的两个参数的构造

总结

  • 继承中的构造函数的特点:
    • 执行顺序是先执行父类的构造函数,再执行子类的,从老祖宗开始,依次一代一代向下执行
    • 父类中的无参构造函数很重要,如果被顶掉,子类中就无法默认调用无参构造了
  • 子类使用父类构造函数时报错的解决方法:
    • 始终保持申明一个无参构造
    • 通过base关键字调用指定父类的构造
  • 注意:区分thisbase的区别,base是调用父类,this是调用自己

16.2 知识点代码

using System;

namespace Lesson14_继承_继承中的构造函数
{
    #region 知识回顾
    //构造函数的作用
    //实例化对象时调用的函数
    //主要用来初始化成员变量
    //每个类 都会有一个默认的无参构造函数

    //构造函数的语法
    // 访问修饰符 类名()
    // {
    // }

    //构造函数的特点
    //不写返回值
    //函数名和类名相同
    //访问修饰符根据需求而定,一般为public
    //构造函数可以重载
    //可以用this语法重用代码

    //注意
    //有参构造会顶掉默认的无参构造
    //如想保留无参构造需重载出来

    //实例
    class Test
    {
        public int testI;
        public string testStr;
        public Test()
        {

        }

        public Test(int i)
        {
            this.testI = i;
        }
        public Test(int i, string str) : this(i)
        {
            this.testStr = str;
        }
    }
    #endregion

    //class语句块外 namespace语句块内

    #region 知识点一 继承中的构造函数 基本概念
    //特点
    //当申明一个子类对象时
    //先执行父类的构造函数
    //再执行子类的构造函数

    //注意:
    //1.父类的无参构造 很重要
    //2.子类可以通过base关键字 代表父类 调用父类构造
    #endregion

    #region 知识点二 继承中构造函数的执行顺序
    // 父类的父类的构造——>。。。父类构造——>。。。——>子类构造

    //游戏对象类
    class GameObject
    {
        public GameObject()
        {
            Console.WriteLine("GameObject的构造函数");
        }
    }
    //玩家类
    class Player:GameObject
    {
        public Player()
        {
            Console.WriteLine("Player的构造函数");
        }
    }
    //主玩家类
    class MainPlayer : Player
    {
        public MainPlayer()
        {
            Console.WriteLine("MainPlayer的构造函数");
        }
    }
    #endregion

    #region 知识点三 父类的无参构造函重要

    //子类实例化时 默认自动调用的 是父类的无参构造 所以如果父类无参构造被顶掉 会报错

    //父类
    class Father
    {
        //当父类无参构造函数被顶掉或者不存在的时候
        //子类会会报错 因为Son son = new Son();  会默认调用父类的无参构造函数
        //public Father()
        //{

        //}

        public Father(int i)
        {
            Console.WriteLine("Father的一个参数的构造");
        }
    }

    //子类

    class Son :Father
    {
        #region 知识点四 通过base调用指定父类构造
        //子类内

        //通过base调用Father的一个参数的构造函数
        public Son(int i) : base(i)
        {
            Console.WriteLine("Son的一个参数的构造");
        }

        //通过this调用Son的一个参数的构造函数
        public Son(int i, string str) : this(i)
        {
            Console.WriteLine("Son的两个参数的构造");
        }

        #endregion
    }

    #endregion


    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("继承中的构造函数");

            //主函数内
            #region 知识点二 继承中构造函数的执行顺序
            MainPlayer mainplayer = new MainPlayer();
            //GameObject的构造函数
            //Player的构造函数
            //MainPlayer的构造函数
            #endregion

            #region 知识点三 父类的无参构造函重要
            //Son son = new Son();//报错 父类无参构造函数被顶掉或者不存在
            #endregion

            #region 知识点四 通过base调用指定父类构造
            Son son = new Son(1, "123");
            //Father的一个参数的构造
            //Son的一个参数的构造
            //Son的两个参数的构造
            #endregion
        }
    }

    //总结

    //继承中的构造函数的特点:
    //执行顺序 是先执行父类的构造函数 再执行子类的 从老祖宗开始 依次一代一代向下执行
    //父类中的无参构造函数 很重要 如果被顶掉 子类中就无法默认调用无参构造了

    //子类使用父类构造函数时报错的解决方法:
    //1.始终保持申明一个无参构造
    //2.通过base关键字 调用指定父类的构造

    //注意:区分this和base的区别 base是调用父类 this是调用自己
}

16.3 练习题

打工人基类及其派生类

程序员、策划、美术分别继承打工人
请用继承中的构造函数这个知识点
实例化3个对象,分别是程序员、策划、美术

class语句块外 namespace语句块内

//打工人类
class Worker
{
    public string type;
    public string content;

    public Worker(string type, string content)
    {
        this.type = type;
        this.content = content;
    }

    public void Work()
    {
        Console.WriteLine("{0}{1}", type, content);
    }
}

//程序员类
class Programmer : Worker
{
    public Programmer() : base("程序员", "编程")
    {

    }
}

//策划类
class Plan : Worker
{
    public Plan() : base("策划", "设计游戏")
    {

    }
}

//美术类
class Art : Worker
{
    public Art() : base("美术", "画画")
    {

    }
}

主函数内

// 主函数内
Programmer p = new Programmer();
p.Work();
//程序员编程

Plan p2 = new Plan();
p2.Work();
//策划设计游戏

Art p3 = new Art();
p3.Work();
//美术画画

在这里,通过构造函数的继承,每个派生类在实例化时就会调用基类的构造函数,从而初始化特征属性。这样,通过继承和构造函数的组合,可以更方便地创建具有相似特征和行为的类。


16.4 练习题代码

using System;

namespace Lesson14_练习题
{
    #region 练习题一
    //有一个打工人基类,有工种,工作内容两个特征,一个工作方法
    //程序员、策划、美术分别继承打工人
    //请用继承中的构造函数这个知识点
    //实例化3个对象,分别是程序员、策划、美术

    //class语句块外 namespace语句块内

    //打工人类
    class Worker
    {
        public string type;
        public string content;

        public Worker(string type, string content)
        {
            this.type = type;
            this.content = content;
        }

        public void Work()
        {
            Console.WriteLine("{0}{1}", type, content);
        }
    }

    //程序员类
    class Programmer:Worker
    {
        public Programmer():base("程序员", "编程")
        {

        }
    }

    //策划类
    class Plan:Worker
    {
        public Plan():base("策划", "设计游戏")
        {

        }
    }

    //美术类
    class Art:Worker
    {
        public Art():base("美术", "画画")
        {

        }
    }

    #endregion
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("继承中的构造练习题");

            #region 练习题一

            Programmer p = new Programmer();

            p.Work();
            //程序员编程


            Plan p2 = new Plan();
            p2.Work();
            //策划设计游戏

            Art p3 = new Art();
            p3.Work();
            //美术画画

            #endregion
        }
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏