visual C#(十二)使用继承

参考书:《 visual C# 从入门到精通》
第二部分 理解C#对象模型
第12 章 使用继承

12.1 什么是继承

程序设计中,继承的问题就是分类的问题,它反映了类和类的关系。

12.2 使用继承

class DerivedClass:BaseClass{
    ...;
}

DerivedClass派生类将从BaseClass基类继承,基类中的方法将成为派生类的一部分。C#中一个类最多只能从一个其他的类派生。注意不要和C++Java中的继承搞混了,格式上都是有区别的。

12.2.1 复习System.Object类

System.Object类是所有类的根,所有类都隐式派生自System.Object类。所以对于一个类,编译器会悄悄将它重写成以下代码:

class Mannal:System.Object{
    ...;
}

所以定义的所有类都自动继承System.Object类的所有功能,包括ToString方法。

12.2.2 调用基类构造器

派生类还会自动包含来自基类的所有字段。派生类的构造器在执行初始化时最好调用一下基类的构造器。可以使用base关键字来调用基类构造器。

如:

class Mamal{
    public Mamal(String name){
        ...;
    }
    ...;
}
class Horse:Mamal{
    public Horse(String name):base(name);{
        ...;
    }
    ...;
}

如果派生类构造器中不显示调用基类构造器的话,编译器会自动插入对基类的默认构造器的调用:

class Horse:Mamal{
    public Horse(String name):base(){
        ...;
    }
}

12.2.3 类的赋值

MammalHorseWhale定义如下:

class Mammal{
    ...;
}
class Horse:Mamal{
    ...;
}
class Whale:Mammal{
    ...;
}

Horse myHorse=new Horse(...);

Whale myWhale=myHorse;错误,不同类型

但可以这样:Mammal myMammal=myHorse;,合法,MammalHorse的基类。但这样是有限制的。HorseWhale类定义的任何额外的方法都不能通过Mammal类来访问。

12.2.4 声明新方法

派生类定义方法时会屏蔽和基类具有相同签名的方法。这样在编译时会显示警告消息,这时可以用new关键字来消除警告。

class Mammal{
    ...;
    public void Talk(){
        ...;
    }
}
class Horse:Mammal{
    ...;
    new public void Talk(){
        ...;
    }
}

12.2.5 声明虚方法

virtual关键字标记,如System.Object的ToString方法的定义:

namsespace System{
    class Object{
        public virtual string ToString(){
            ...;
        }
        ...;
    }
    ...;
}

故意被设计成被重写的方法称为虚方法

12.2.6 声明重写方法

派生类用override关键字重写基类的虚方法

class Horse:Mammal{
    ...;
    public override string ToString(){
        ...;
    }
}

派生类中方法的新实现可以用base关键字调用方法的基类版本:

public override string ToString(){
    base.ToString();
    ...;
}

使用virtualoverride时必须遵守以下规则:

  • 虚方法不能私有
  • 虚方法和重写方法的签名必须完全一致
  • 只能重写虚方法
  • 如果派生类不用override声明方法,就不是重写基类方法而是隐藏方法
  • 重写方法隐式地成为虚方法,可在派生类中被重写。但不允许用virtual将重写方法显式声明为新方法

12.2.7 理解受保护的访问

除了publicprivate,还有protented关键字:允许基类的派生类访问而阻止其他类访问。


下面我们实际编写代码:

新建下面几个源文件:

Vehicle.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace c12_2_7
{
    class Vehicle
    {
        public void StartEngine(String noiseToMakeWhenStarting)
        {
            Console.WriteLine($"Starting engine:{noiseToMakeWhenStarting}");
        }
        public void StopEngine(string noiseToMakeWhenStopping)
        {
            Console.WriteLine($"Stopping engine:{noiseToMakeWhenStopping}");
        }
        public virtual void Drive()
        {
            Console.WriteLine("Default implementation of the Drive method");
        }
    }
}

Airplane.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace c12_2_7
{
    class Airplane:Vehicle
    {
        public void TakeOff()
        {
            Console.WriteLine("Wu~Hu~, Taking off");
        }
        public void Land()
        {
            Console.WriteLine("Landing");
        }
        public override void Drive()
        {
            Console.WriteLine("Flying");
        }
    }
}

car.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace c12_2_7
{
    class car:Vehicle
    {
        public void Accelerate()
        {
            Console.WriteLine("Accelerate");
        }
        public void Brake()
        {
            Console.WriteLine("Breaking");
        }
        public override void Drive()
        {
            Console.WriteLine("Motoring");
        }
    }
}

主程序Program.cs

using System;

namespace c12_2_7
{
    class Program
    {
        static void dowork()
        {
            Console.WriteLine("Journey by airplane:");
            Airplane myPlane = new Airplane();
            myPlane.StartEngine("Contace");
            myPlane.TakeOff();
            myPlane.Drive();
            myPlane.Land();
            myPlane.StartEngine("Whirr");
            Console.WriteLine("\nJourney by car:");
            car myCar = new car();
            myCar.StartEngine("Brm brm");
            myCar.Accelerate();
            myCar.Drive();
            myCar.Brake();
            myCar.StartEngine("Phut phut");
            Console.WriteLine("\nTesting polymorphism");//测试多态性
            Vehicle v = myCar;
            v.Drive();
            v = myPlane;
            v.Drive();
        }
        static void Main(string[] args)
        {
            dowork();
        }
    }
}

运行结果:
在这里插入图片描述

12.3 理解扩展方法

扩展方法允许添加静态方法来扩展现有的类型。引用被扩展类型的数据可调用扩展方法。

扩展方法在静态类中定义,被扩展的类型必须式方法的第一个参数,而且必须附加this关键字。

static class Util{
    public static int Negate(this int i){
        return -i;
    }
}
int x=591;
Console.WriteLine($"x.Negate {x.Negate}");

下面我们新建一个控制台应用,首先添加一个新建项:

Util.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace C_12_3
{

    static class Util
    {
        public static int ConvertToBase(this int i,int baseToConvertTo)
        {
            if (baseToConvertTo < 2 || baseToConvertTo > 10)
            {
                throw new ArgumentException("Value cannot be converted to base"
                    + baseToConvertTo.ToString());
            }
            int result = 0;
            int iteration = 0;
            do
            {
                int nextDigit = i % baseToConvertTo;
                i /= baseToConvertTo;
                result += nextDigit * (int)Math.Pow(10, iteration);
                iteration++;
            } while (i != 0);
            return result;
        }
    }
}

Program.cs中的代码如下:

using System;
//using C_12_3;
namespace C_12_3
{
    class Program
    {
        static void dowork()
        {
            int x = 591;
            for(int i = 2; i <= 10; ++i)
            {
                Console.WriteLine($"{x} in base {i} is{ x.ConvertToBase(i)}");
            }
        }
        static void Main(string[] args)
        {
            dowork();
        }
    }
}

运行结果如图:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值