C#学习入门(三)—— 抽象类

1.抽象类的概念和定义

抽象类往往用来表征对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。

 在C#中,抽象类可以包含:抽象方法、抽象属性、具体方法和具体属性。

1.1 定义

访问修饰符 abstract class 类名
{
    访问修饰符 abstract 返回值类型 方法名(参数列表); //定义抽象方法
    其他类成员;
}

 抽象类的定义类似于普通类,只不过在访问修饰符后加入abstract

1.2 抽象方法

// 抽象方法
public abstract double GetName();
// 抽象属性
public abstract string Name { get; }

 抽象类中需要加入抽象方法,而抽象方法只需要声明,也就是抽象方法的内容是不用写的,只需要一个空方法。有点类似于C++在头文件中定义方法时,可以只是一个声明,不提供方法体,而在.C文件中才实现该函数。

1.3 重写抽象方法

访问修饰符 class 派生类的类名 : 基类的类名
{
    访问修饰符 override 返回值类型 方法名(参数列表) 
    {
        方法体;
    }
    其他类成员;
}

 在子类继承自基类后,需要重写抽象方法,否则编译器会报错。只需要在方法的访问修饰符后加入override即可。

1.4 抽象类和具体类的区别

(1)抽象类不能实例化,具体类能实例化
(2)抽象类中不一定要有抽象方法,具体类中不能有抽象方法。
(3)抽象类可以和具体类一样,有具体方法。
(4)抽象类可以继承抽象类,子类如果不是抽象类,则必须重写抽象类中的全部抽象方法。
(5)在抽象类中,不能用private修饰抽象方法,因为抽象方法要被子类重写。
(6)在以下情况,一个类将成为抽象类:
   <1>当一个类的一个或多个方法是抽象方法。
   <2>当类是一个抽象类的子类,但是不能为任何抽象方法提供任何实现细节或方法实体。
   <3>当一个类实现一个接口,但是不能为任何抽象方法提供任何实现细节或方法实体。

1.5 多态

根据抽象类,可以总结多态为一下几点:
(1)使用基类类型的引用指向子类的对象,但是该引用只能调用父类定义的方法和变量。
(2)如果派生类重写了基类的方法,那么派生类调用该方法时会调用派生类自己的方法(动态链接、动态调用)。
(3)一个类型引用只能引用类型自身含有的方法和变量。

2. 实现的案例

2.1 例子

// pet抽象类
public abstract class Pet //基类,抽象类,定义宠物类
{
    public String Name {  get; set; } //宠物名字
    public String Gender { get; set; } //宠物性别
    public int Health { get; set; } //宠物健康值
    public abstract void ToHospital(); //看病方法
    public abstract void Eat();
}
// Dog具体类
class Dog : Pet //派生类,定义小狗类
{
    public override void ToHospital() //重写看病方法
    {
        Console.WriteLine("打针、吃药");
    }

    public override void Eat() //重写看病方法
    {
        Console.WriteLine("吃狗粮!");
    }
}
// Cat具体类
public class Cat : Pet //派生类,定义猫咪类
{
    public override void ToHospital() //重写看病方法
    {
        Console.WriteLine("输液、疗养");
    }

    public override void Eat() //重写看病方法
    {
        Console.WriteLine("吃猫粮!");
    }
}
// Doctor
class Doctor //定义医生类
{
    public void Cure(Pet pet) //治疗方法
    {
        if (pet.Health < 50)
        {
            pet.ToHospital();
            pet.Health = 60;
        }
    }
}
// 主函数
class Program
{
    static void Main(string[] args)
    {
        Pet pet;
        Dog dog;
        
        pet = new Dog();
        dog = pet as Dog;
        if (dog != null)
        {
            dog.Eat();
        }
        else
        {
            Console.WriteLine("转换失败了!!!");
        }
    }
}

 pet = new Dog();使用基类对象指向派生类对象,派生类对象转换为基类对象,是安全的转换,也就是向上转换类型,一般是隐式转换
 对于基类中定义的方法,如果派生类中重写了该方法,那么基类类型的引用将会调用派生类中的这个方法,这就是多态。
 使用基类对象指向派生类对象,那么该基类对象可以指向任意一个派生类对象,可以随意切换,非常方便。

2.2 向下转换

派生类对象 = (派生类名)基类对象;

 但是,当将基类对象转换为派生类对象,向下转换时,是很不安全的。为此默认情况下,进行向下转型时,往往会发生编译错误。然而,有时候确实需要强制转换,这时候就需要异常处理。

3. 异常处理

3.1 try-catch

try
 {
      Pet pet = new Cat();
      Dog d = (Dog)pet;
 }
 catch
 {
     Console.WriteLine(“类型转换出错!");
 }

 Cat和Dog都是pet的派生类,当然不能互相转换,类型转换出错。

3.2 使用as和is

//使用 as
Dog  dog =  pet as Dog
if(dog==null)
         Console.WriteLine(“转换不成功!);
//使用 is
pet = new Cat();
if (pet is Dog)
{
    dog = (Dog)pet;
    dog.Eat();
}
else
{
    Console.WriteLine("不是Dog的实例");
}

 使用is和as,再进行强制转换,这样能够更加安全地进行转换,转换错误后程序能继续运行下去,不用抛出异常。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暗夜无风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值