关于父类引用指向子类对象

例如: 有以下2个类

public  class  Father
        {
            public int age = 70;
            public static string name = "父亲";
        }

        public class Son : Father
        {
            public int age = 30;
            public static string name = "儿子";    

        }

Father f=new Son();

这种用法叫做“父类引用指向子类对象,或者叫“父类指针指向子类对象”,指的是定义一个父类的引用,而它实际指向的是子类创建的对象。

好处是什么?

下面做几个测试,

第一种  ,父类变量,调用 属性  例如下面的  f.age   是一个父类的变量调用了属性,问题是这里的属性是父类的?还是子类的? 答案是父类的属性

class Program
    {
        static void Main(string[] args)
        {
            Father f=new Son();
            Console.WriteLine(f.age);   //这里输出的是父类的年龄?还是子类的年龄? 答案是父亲的年龄 70 ,因为这里的f是个父类类型,所以是调用父类的属性

            Son s = f as Son;
            Console.WriteLine(s.age);  //这里输出的父类的年龄?还是子类的年龄? 答案是子类的年龄 30

            Console.ReadKey();
        }

        public  class  Father
        {
            public int age = 70;                      //第4执行
            public static string name = "父亲";       //第3执行
        }

        public class Son : Father
        {
            public int age = 30;                    //第2执行
            public static string name = "儿子";    //第1执行

        }
    }

小结论(1): 当用父类的变量调用属性的时候,取决于声明的类型(“=”左边是什么类型),而不是后面实例化的类型

第二种 ,父类变量,调用 方法 (父类的方法和子类的方法  一模一样,子类并无重写)

public  class  Father
        {
            public int age = 70;                      //第4执行
            public static string name = "父亲";       //第3执行

            public void SayHi()
            {
                Console.WriteLine(string.Format("父亲说,年龄{0},名字是{1}",age,name));
            }

        }

        public class Son : Father
        {
            public int age = 30;                    //第2执行
            public static string name = "儿子";    //第1执行

            public void SayHi()
            {
                Console.WriteLine(string.Format("儿子说,年龄{0},名字是{1}", age, name));
            }
        }

static void Main(string[] args)
        {

            Father f = new Son();
            f.SayHi();   //这里调用的是父类的方法,因为f是父类,并且子类,压根就没有重写   父亲说,年龄是70,名字是父亲

            Son s = f as Son;
            s.SayHi();   //这里调用的是父类的方法?还是子类的方法?  答案是子类的方法,因为s是子类   儿子说,年龄是30,名字是儿子
            Console.ReadKey();
        }

小结论(2): 当子类和父类的方法完全相同时,调用的时候取决于声明的类型(“=”左边),而不是后面实例化的类型。

第三种 ,父类变量,调用 方法 (父类的方法和子类的方法 一模一样 ,但是父类的方法加 Virtual , 子类不重写)

小结论(3):如果父类有virtual虚方法,但是子类并没有重写的话,那么  同上面的小结论(2)一样,调用的时候,取决于声明的类型(“=”的左边),而不是实例化的类型

第四种 ,父类变量,调用 方法 (父类的方法和子类的方法 一模一样 ,但是父类的方法加 Virtual , 子类重写)

小结论(4):重写以后,调用哪个类的方法取决于实例化的类型(“=”右边)或者是转换后最终的类型

第五种 ,父类变量,调用 方法 (父类的方法和子类的方法 一模一样 ,但是父类的方法加 Virtual , 子类重写)

父类变量指向子类的实例,但是我们直接调用父类变量下的属性,会输出子类的属性?还是父类的属性?答案是父类的属性.

那如果再继续调用方法的话,是调用父类的方法?还是子类的方法?答案是,如果是虚方法,子类有重写,就调用子类的,子类没有重写,就调用父类的.

小结论(5) : 如果子类方法里面想调用父类的属性或者是方法,使用 base 关键字

结论:

1:当用父类的变量调用属性的时候,取决于声明的类型(“=”左边是什么类型),而不是后面实例化的类型

例如 输出 f.age 就是输出父类的属性 ,而不是子类的属性

2:当子类和父类的方法完全相同时,调用的时候取决于声明的类型(“=”左边),而不是后面实例化的类型。

也就是子类没有重写的时候. f.sayhi 就是调用的父类的sayhi ,而不是子类的sayhi

3 如果子类有重写(override)父类的方法,那么 父类变量调用方法的时候,就变成使用 子类的方法.

也就是子类有override的时候,f.sayhi 就是调用子类的sayhi

4:如果想在子类里面访问父类的属性或者是方法,使用 base 关键字

C#中new和override的区别;abstract

当父类里面有 virtual 方法的时候,子类可以使用 override 进行重写.  那么  f.sayhi  就变成调用子类的sayhi

不论父类的方法有没有virtual,子类都可以在同名的方法上加一个new表示这是子类自己的方法,那么父类的方法就会被隐藏起来, f.sayhi 就会变成 调用父类的sayhi,因为子类并没有override. 如果这个时候,把new去掉,效果也是一样的,f.sayhi 也是调用父类的sayhi, 判断是否调用子类的方法,就看子类是否有override重写.

//在C#中,override和new都会覆盖父类中的方法。那它们两者之前有什么区别呢? //override是指“覆盖”,是指子类覆盖了父类的方法。子类的对象无法再访问父类中的该方法(当然了,在子类的方法中还是可以通过base访问到父类的方法的)。

//new是指“隐藏”,是指子类隐藏了父类的方法,当然,通过一定的转换,可以在子类的对象中访问父类的方法。

c#类的初始化顺序

子类的静态成员变量,子类的普通成员,父类的静态成员,父类的普通成员

namespace 类的初始化顺序
{
    class Program
    {
        static void Main(string[] args)
        {
            Father f=new Son();
            Console.ReadKey();
        }

        public  class  Father
        {
                 public int age = 70;                            //第4执行
            public static string name = "父亲";       //第3执行
        }

        public class Son : Father
        {
                 public int age = 30;                         //第2执行
            public static string name = "儿子";    //第1执行

        }
    }
}

首次访问:(在此没有显示的写出类中的构造方法) 
顺序:子类的静态字段==》子类静态构造==》子类非静态字段==》父类的静态字段==》父类的静态构造==》父类的非静态字段 
==》父类的构造函数==》子类的构造函数 
非首次访问:顺序是一样的,只不过少了中间静态字段和构造的过程 
对于静态变量与静态构造函数而言, 无论对一个类创建多少个实例,它的静态成员都只有一个副本。 也就是说,静态变量与静态构造函数只初始化一次(在类第一次实例化时)

时间: 2024-10-07 01:24:35

关于父类引用指向子类对象的相关文章

父类引用指向子类对象

1 public class Test { 2 /** 3 * 对于多态,可以总结它为: 4 5 一.使用父类类型的引用指向子类的对象: 6 7 二.该引用只能调用父类中定义的方法和变量: 8 9 三.如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法:(动态连接.动态调用) 10 11 四.变量不能被重写(覆盖),”重写“的概念只针对方法,如果在子类中”重写“了父类中的变量,那么在编译时会报错. 12 13 多态的3个必要条件: 14 15 1.继承 2.重写

理解父类引用指向子类对象

java多态,如何理解父类引用指向子类对象 要理解多态性,首先要知道什么是“向上转型”. 我定义了一个子类Cat,它继承了Animal类,那么后者就是前者是父类.我可以通过   Cat c = new Cat(); 实例化一个Cat的对象,这个不难理解. 但当我这样定义时:   Animal a = new Cat(); 这代表什么意思呢? 很简单,它表示我定义了一个Animal类型的引用,指向新建的Cat类型的对象.由于Cat是继承自它的父类Animal,所以Animal类型的引用是可以指向C

java父类引用指向子类对象

父类引用指向子类对象指的是: 例如父类Animal,子类Cat,Dog.其中Animal可以是类也可以是接口,Cat和Dog是继承或实现Animal的子类. Animal animal = new Cat(); 即声明的是父类,实际指向的是子类的一个对象. 那这么使用的优点是什么,为什么要这么用?可以用这几个关键词来概括:多态.动态链接,向上转型 也有人说这是面向接口编程,可以降低程序的耦合性,即调用者不必关心调用的是哪个对象,只需要针对接口编程就可以了,被调用者对于调用者是完全透明的.让你更关

java多态,如何理解父类引用指向子类对象

摘录 要理解多态性,首先要知道什么是“向上转型”. 我定义了一个子类Cat,它继承了Animal类,那么后者就是前者是父类.我可以通过   Cat c = new Cat(); 实例化一个Cat的对象,这个不难理解. 但当我这样定义时:   Animal a = new Cat(); 表示定义了一个Animal类型的引用,指向新建的Cat类型的对象.由于Cat是继承自它的父类Animal,所以Animal类型的引用是可以指向Cat类型的对象的. 那么这样做有什么意义呢?因为子类是对父类的一个改进

【转】父类引用指向子类对象

父类引用指向子类对象指的是: 例如父类Animal,子类Cat,Dog.其中Animal可以是类也可以是接口,Cat和Dog是继承或实现Animal的子类. Animal animal = new Cat(); 即声明的是父类,实际指向的是子类的一个对象. 那这么使用的优点是什么,为什么要这么用?可以用这几个关键词来概括:多态.动态链接,向上转型 也有人说这是面向接口编程,可以降低程序的耦合性,即调用者不必关心调用的是哪个对象,只需要针对接口编程就可以了,被调用者对于调用者是完全透明的.让你更关

父类引用指向子类对象--面向对象的多态

先上代码 package com.fuzi.demo; public class FuZi { public static void main(String[] args) { FuLei fuLei = new ZiLei(); fuLei.print_info(); } } class FuLei { public void print_info() { System.out.println("父类的print_info"); System.out.println(this.get

理解多态AND理解父类引用指向子类对象

假设现在有一个父类Father,它里面的变量需要占用1M内存.有一个它的子类Son,它里面的变量需要占用0.5M内存. 现在通过代码来看看内存的分配情况: Father f = new Father();//系统将分配1M内存. Son s = new Son();//系统将分配1.5M内存. 因为子类中有一个隐藏的引用super会指向父类实例,所以在实例化子类之前会先实例化一个父类,也就是说会先执行父类的构造函数. 由于s中包含了父类的实例,所以s可以调用父类的方法. Son s1 = s;/

JAVA基础复习与总结<一>(2) 父类引用指向子类对象(向上转型、动态链接)

public class Animal { public static void main(String[] args){ Animal animal = new Cat(); animal.voice(); drinkWater(animal); //调用静态方法,传入的是父类引用的子类对象 } String str; public void voice(){ System.out.println("普通动物叫声!"); } public static void drinkWater

父类引用指向子类对象详解

父类引用变量引用子类时可以调用子类覆盖的方法. 举个例子: 假设有类Cat,类Dog,类Duck...他们都有一个继承自父类Animal的方法eat(),各自覆盖了这个方法,因为猫狗鸭吃相不同 现在.我有另一类,里面有个方法处理各种动物的吃相all_eat() 当然你可以这么写: // 需要用到某个类型时给其创建对象 public Cat cat = null; public Dog dog = null; public Duck ducl = null; public void all_eat