黑马程序员 - 学习笔记4 里式转换原则的学习

来源:互联网 发布:java开发手册 怎么样 编辑:程序博客网 时间:2024/05/23 12:07

---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------详细请查看:www.itheima.com

里式转换原则的学习

通过学习,掌握了里式转换原则。

里式转换原则
(1)子类可以直接赋值给父类
(2)父类可以强制类型转换为“对应”的子类
里式转换原则的存在价值就是用来实现多态


我们先来谈谈第一点,什么叫做子类可以直接赋值给父类呢?我们配合代码来看:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace 里氏转换原则
{
    class Program
    {
        static void Main(string[] args)
        {
            Chinese c1 = new Chinese();//创建一个 Chinese 对象  
            c1.Name = "Mr Lucky";
            Person p1 = c1;//子类直接赋值给父类


        }
    }


    class Person//定义一个Person类  所有类的父类
    {
        string name;//定义一个 name 字段


        public string Name
        {
            get { return name; }
            set { name = value; }
        }


    }

    class Chinese : Person//定义一个类,中国人   继承自Person类
    {
        public void SayHello()
        {
            Console.WriteLine("你好,我是中国人!");
        }
 
    }

    class American : Person//定义一个类,美国人    继承自Person类
    {
        public void SayHello()
        {
            Console.WriteLine("你好,我是美国人!");
        }
    }

    class Japanese : Person//定义一个类,日本人   继承自Person类
    {
        public void SayHello()
        {
            Console.WriteLine("你好,我是日本人!");
        }
    }
}

我们创建了一个 Person 父类,后面分别写了3个子类,都继承自 Person 类,接着,在主方法中创建了一个 Chinese 类的对象,并将继承自父类的字段 name 赋值,最后,直接将创建好了的对象 c1 赋值给 Person 类,

也就是直接将子类直接赋值给父类,调试代码发现,没有任何错误,这也就实现了里氏转换原则中的 “子类可以直接赋值给父类”。

我们创建了三个子类,如何统一管理呢?总不能new 一个子类,然后再 Person p=XX XX,这样很麻烦,我们还可以用数组将他们统一起来:

static void Main(string[] args)
        {
            Chinese c1 = new Chinese();
            c1.Name = "幸运先生";


            American a1 = new American();
            a1.Name = "Mr lucky";


            Japanese J1 = new Japanese();
            J1.Name = "にねのせ";


            Person[] per = { c1,a1,J1};
        }
现在,我们将 Chinese 类, American 类, Japanese 类都赋给了 Person 类,那么,现在这三个子类是什么类型的呢?在这里,三个子类就是 Person 类型的了。
还要和大家说明的是,父类只能访问父类的成员,我们看图:

在里氏转换原则第一条当中,子类直接可以赋值给父类,所以可以直接将 c1、a1、J1 存入 person类型 的数组当中,首先我们知道 Person[0] 代表的是 Chinese 类,也就是 c1 ,此时的 c1 因为直接赋值给了父类,所以是 Person 类型,也就造成了我们在用 per[0] 点的时候,只点出了 name 字段的属性 Name,而 Chinese 中的 SayHello() 方法是无法点出来的,这也就是我刚才说的,父类只能访问父类的成员。




但是我现在就想调用子类中 SayHello(),怎么办呢? 这就使用到了我们里氏转换原则中的第二条,指向子类的父类,可以强制转换为对应的子类。强制转换,大家应该都会吧!


看下面如何进行强制转换:

 Person[] per = { c1,a1,J1};
            //per[0]. 父类只能访问父类的成员  无法访问子类的成员,想要访问 可以进行强制转换  里氏原则中的第二条
            ((Chinese)per[0]).SayHello();
            Console.ReadKey();

得到的结果:


里氏原则第二条,指向子类的父类,可以强制转换为对应的子类,当我们进行强制转换以后,那么现在的 per[0] 就不在是 person 类型的了,而是 Chinese 类型的,所以我们可以点出 SayHello() 方法。

我把代码改一下:
((American)per[0]).SayHello();

上面是将 per[0] 强制转换成 Chinese 类,我们发现是可以的,那么,当我改成 American 的时候,可不可以呢!调试一下:


调试之后,发现报错了…… 为什么可以强制转换成 Chinese 类型,不可以强制转换成 American 类型呢?我们来分析一下:


再看一遍里氏转换原则第二点:


指向子类的父类,可以强制转换为对应的子类。


仔细看,可以强制转换为 对应 的子类,我将 对应 加粗了一下并下划线,记住:对应、对应 。


在 per[0] 这块区域中我们预存的是 Chinese 类型的对象 c1,并不是 American 类型的 a1,我们想将 per[0] 强制转换,就只能转换成 Chinese 类型,因为我们原本在 per[0]中存的就是 Chinese 类型的对象,这也遵循了里氏转换原则第二条“指向子类的父类,可以强制转换为对应的子类”,记住,对应,对应。

 per[1] 、per[2] 也只能对应的强制转换成 American 类型 和 Japanese 类型。


通过以上的例题学习后我的感想


问题一 什么是强制类型转换(显示转换)    

简单表达就是  

double x = 123.11

int y = (int)x

问题二 哪一个是对应的子类

上面提到per[]数组是person类型,而数组中的c1是Chinese类型   //(声明(new) c1 的时候就确定了c1是 chinese类 型,由于将c1加入到person数组中,所以变成person类型)

如果要将person类强制转换成子类,必须转换成对应的子类,比如per[0]是 Chinese类型,per[1]是American类型


到目前为止,对代表复杂多态的里式转换原则,有了初步的了解,能够懂得原则中所谓的两个基础点。

需要在以后的实际操作中,巩固此知识点。

---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------详细请查看:www.itheima.com

0 0
原创粉丝点击