黑马程序员--里氏转换

---------------------- 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();
        }
原文地址:https://www.cnblogs.com/tobecabbage/p/3459867.html