C# 类继承(知识要点归纳总结)

C# 类继承(知识要点归纳总结)

1.覆盖

有时希望子类继承基类的大部分行为,但是并不是所有行为。如果希望改变一个类继承的某些行为,可有覆盖(override)这些方法。

实现方法:

  • 为基类中的方法增加virtual关键字。
    子类智能覆盖标志有virtual关键字的方法,这就告诉C#允许子类覆盖这些方法。
//基类
class Bird
{
    public virtual void Fly()
    {
        // code to make the bird fly
    }
}
  • 为派生类增加一个同名方法。
    这个方法要有完全相同的方法签名,这说明返回值和参数都要相同而且声明中要使用override关键字。
//子类
class Penguin : Bird
{
    public override void Fly()
    {
        MessageBox.Show("Penguin can't fly!")
    }
}

2.向要求基类作为形参的函数传入子类

对于继承,最有用的一点就是可以使用子类来取代它继承的基类。但是函数只能访问形参中基类的成员,不能访问子类中特有的成员。

//基类
class Bird
{
    public virtual void Fly()
    {
        // code to make the bird fly
    }
}

//子类
class Penguin : Bird
{
    public override void Fly()
    {
        MessageBox.Show("Penguin can't fly!")
    }
}

internal class Program
{
    private static void Main()
    {
        HuntBird(new Penguin);
        Console.ReadKey();
    }

    private void HuntBird(Bird bird)
    {
        bird.Fly();
    }
}

3. override和new的区别

二者的不同主要体现在,基类的引用变量指向子类实例对象时,即把子类的对象转化成基类类型。当变量调用被override或者new后的方法时,表现为如下不同:
- override的方法,会覆盖基类中的方法,用该变量调用这个方法时,总是调用子类中的方法;
- new的方法,会隐藏基类中的方法,用该变量调用这个方法时,总是调用基类中的方法。

代码示例:

//基类
class Bird
{
    public virtual void Fly1()
    {
        Console.WriteLine("Bird Fly1");
    }

    public virtual void Fly2()
    {
        Console.WriteLine("Bird Fly2");
    }
}

//子类
class Penguin : Bird
{
    public override void Fly1()
    {
        Console.WriteLine("Penguin Fly1");
    }

    public new void Fly2()
    {
        Console.WriteLine("Penguin Fly2");
    }
}

internal class Program
{
    private static void Main()
    {
        Bird b1 = new Penguin();
        b1.Fly1();//输出"Penguin Fly1"
        b2.Fly2();//输出"Bird Fly2"

        Console.ReadKey();
    }

    private void HuntBird(Bird bird)
    {
        bird.Fly();
    }
}

备注:在建立类层次结构时,通常是覆盖方法而不是隐藏方法。如果确实是要隐藏方法,就要使用new关键字。


3. virtual和abstract的区别

  1. virtual修饰的方法必须要有实现(只有一对大括号也可以),abstract修饰的方法不能有实现;
  2. virtual修饰的方法在子类中可以重写也可以不重写,abstract修饰的方法在子类中必须要重写;
  3. 只有类被修饰为abstract,该类中的函数才能被修饰为abstract;
  4. abstract修饰的类不能实例化;
  5. 如果要重写基类中virtual修饰的方法,子类中的该方法要用override修饰。

4. 子类用base关键字访问其基类

计时子类覆盖了基类中的方法或属性,有时仍需要访问基类中的成员。使用base关键字可以访问基类中的任何方法。

using System;

namespace base关键字
{
    internal class Program
    {
        private static void Main()
        {
            var child = new ClassChild();
            child.F2();

            Console.ReadKey();
        }
    }

    //基类
    internal class ClassBase
    {
        public virtual void F1()
        {
            Console.WriteLine("base F1");
        }
    }

    //子类
    internal class ClassChild : ClassBase
    {
        public override void F1()
        {
            Console.WriteLine("child F1");
        }

        public void F2()
        {
            base.F1();//调用基类函数
        }
    }
}

上面代码输出:
base F1

5. 基类中有构造函数,子类中也要有构造函数

如果基类中有构造函数(尤其是当有带参数的构造函数),继承这个类的所有子类必须调用其中一个构造函数。

using System;

namespace 子类构造函数
{

    internal class Program
    {
        private static void Main()
        {
           var child= new ClassChild("正在调用子类的构造函数",11);

            Console.ReadKey();
        }
    }

    //基类
    internal class ClassBase
    {
        public ClassBase(string information)
        {
            Console.WriteLine("base class constructor" + information);
        }
    }

    //子类
    internal class ClassChild : ClassBase
    {
        //调用子类的构造函数前先调用基类的构造函数
        public ClassChild(string information, int number) : base(information)
        {
            Console.WriteLine("child class constructor" + information + number);
        }
    }
}

备注:子类实例化时先调用基类构造函数,再调用子类构造函数。

posted on 2017-09-23 09:55  五月槐花  阅读(123)  评论(0编辑  收藏  举报

导航