zoukankan      html  css  js  c++  java
  • 黑马程序员--里氏转换

    ---------------------- ASP.Net+Android+IOS开发 .Net培训期待与您交流! ----------------------

    ?如果有一个非静态类,当我们在线程栈你创建了引用变量,但没有使用new方法创建对象时,该引用变量可以使用点运算符点出类的成员吗

    答案是:经调试发现是可以的

    说明:变量类型决定可以点出的什么成员,(专业术语来说,就是引用变量决定指针偏移量).但是,若要给点出的成员赋值或者使用它,必须使用new创建对象,以给它分配内存

     里氏转换

    ■子类对象可以无条件的赋值给父类: 父类类型名  引用变量名=new 子类对象();如base b=new sub();

    ■若一个父类的引用变量指向一子之类对象,那么可以父类引用变量强制赋强制转化为子类赋值给子类变量.sub s=(sub)b;

    ( 概括:一个父类引用可以指向一个子类对象,但一个子类引用不能指向一个父类对象.因为子类的指针偏移量较父类要大,好比将一个long类型的大数(子类引用变量)放在一个int类型的内存空间(父类对象),这样肯定会出错.

      通俗的解释就是:引用变量好比标签,动物类派生出一个狗类,狗对象贴动物标签可以,但是一个具体的动物贴个狗标签是不合理的.)

      为什么说子类的引用指针偏移量要打呢?因为子类的引用不仅可以点出父类的成员,还能点出自己的附加成员.

      引用类型与值类型有点不一样,值类型是变量分配内存空间,引用类型是new()分配内存空间,引用类型的引用变量好比值类型的数值,如下

      long big=320000000000000000000000000000;         int little=32;                  

        big=32;//  对                                                         little=3200000000000000000000000000000000000000; //错

        new sub()=b base;  //对                                         new base()=s  sub //错

    以上理解为new sub()相对于long类型变量这个大空间(指针偏移量大),大空间能装的下这个b小数

    new base()为这个相对于int类型变量这个小空间,小空间装不了s这个大数

     public class Person//基类,或称为父类
        {
            private string name;
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
            private int age;
            public int Age
            {
                get { return age; }
                set { age = value; }
            }
            private char gender;
            public char Gender
            {
                get { return gender; }
                set { gender = value; }
            }
            public Person()//建议只要自己声明了无参构造方法,务必再声明一个无参构造方法.系统默认会调用无参构造方法
            {
                Console.WriteLine("我是父类");
            }
            public Person(string name, int age, char gender):this()
            {
                this.Name = name;
                this.Age = age;
                this.Gender = gender;
            }
            public void Say()
            {
                Console.WriteLine("我是{0},我今年{1}岁了,我是{2}生", name, age, gender);
            }
        }
     public class Teacher:Person//继承类,或称子类
        {
            private string course;
            public string Cource
            {
                set{course=value;}
                get{return course;}
            }
            private int yearsOfService;
            public int YearsOfService
            {
                set { yearsOfService = value; }
                get { return yearsOfService; }
            }
        
            public void SayHello()
            {
                Console.WriteLine("你们好,我是{0},我今年{1}岁了,教书{2}年了,我是{3}老师", Name, Age, yearsOfService, course);
            }
            public Teacher(string name,int age,char gender,string course,int yearsOfService):base( name, age, gender)
                //此处若没写base(name,age,gender)构造方法,便是默认调用Person的无参构造方法即base()
            {
                this.course = course;
                this.yearsOfService = yearsOfService;
            }
        }
     public class Student : Person//继承类Student
        {
            private int classId;
            public int ClassId
            {
                set { classId = value; }
                get { return classId; }
            }
            private string hobby;
            public string Hobby
            {
                set { hobby = value; }
                get { return hobby; }
            }
            public void SayHello()
            {
                Console.WriteLine("大家好,我是{0},我今年{1}岁了,我是{2}生,我是{3}班的,我喜欢{4}", Name, Age, Gender, classId, hobby);//包含基类的成员,加自己的成员,除了基类的私有成员外,其余成员都能访问到
            }
            public Student(string name,int age,char gender,int classId,string hobby):base(name,age,gender)//父类构造方法执行之后才执行
            {
                this.hobby = hobby;
                this.classId = classId;
            }
         
            }
    class Program
        {
            static void Main(string[] args)
            {
                //依次做自我介绍
                Person[] ps = new Person[]{
                    new Teacher("翟群",23,'',"c#",0),
                    new Student("何雄军",24,'',2,"计算机"),
                    new Person("呵呵",23,'')
                };
                //使用基类的引用访问不到子类的成员,所以要进行里氏转换,以访问到子类的成员
                for (int i = 0; i < ps.Length; i++)
                {
                    if (ps[i] is Teacher)//判断是否为Teacher类型对象
                    {
                        ((Teacher)ps[i]).SayHello();
                        //结果:你们好,我是翟群,我今年23岁了,,我教书0年了,我是c#老师
                    }
                    else if (ps[i] is Student)
                    {
                        ((Student)ps[i]).SayHello();
                        //结果: 大家好,我是何雄军,我今年24岁了,我是男生,我是2班的,我喜欢计算机
                    }
                    else
                    {
                        ps[i].Say();
                        //结果:我是呵呵,我今年23岁了,我是女生.
                    }
                }
                //Teacher t = (Teacher)ps[2];
               // Teacher t = ps[2] as Teacher; as转换符等同与以下
                Teacher t = ps[2] is Teacher ? ((Teacher)ps[2]) : null;
                Console.ReadKey();
            }
  • 相关阅读:
    最近迷上用dvd字幕学习英语
    原始套接字
    c语言socket编程
    inet_aton和inet_network和inet_addr三者比较
    用man来查找c函数库
    ubuntu的系统日志配置文件的位置
    复制文件
    vim复制粘贴解密(转)
    vim的自动补齐功能
    两个数据结构ip和tcphdr
  • 原文地址:https://www.cnblogs.com/tobecabbage/p/3459867.html
Copyright © 2011-2022 走看看