父类引用指向子类对象

来源:互联网 发布:卡西欧自拍神器软件 编辑:程序博客网 时间:2024/05/21 07:12
父类引用指向子类对象
从对象的内存角度来理解试试.
假设现在有一个父类Father,它里面的变量需要占用1M内存.有一个它的子类Son,它里面的变量需要占用0.5M内存.
现在通过代码来看看内存的分配情况:
Father f = new Father();//系统将分配1M内存.
Son s = new Son();//系统将分配1.5M内存!因为子类中有一个隐藏的引用super会指向父类实例,所以在实例化子类之前会先实例化一个父类,也就是说会先执行父类的构造函数.由于s中包含了父类的实例,所以s可以调用父类的方法.
Son s1 = s;//s1指向那1.5M的内存.
Father f1 = (Father)s;//这时f1会指向那1.5M内存中的1M内存,即是说,f1只是指向了s中实例的父类实例对象,所以f1只能调用父类的方法(存储在1M内存中),而不能调用子类的方法(存储在0.5M内存中).
Son s2 = (Son)f;//这句代码运行时会报ClassCastException.因为f中只有1M内存,而子类的引用都必须要有1.5M的内存,所以无法转换.
Son s3 = (Son)f1;//这句可以通过运行,这时s3指向那1.5M的内存.由于f1是由s转换过来的,所以它是有1.5M的内存的,只是它指向的只有1M内存. 
--这是什么玩意儿?
re:这种用法叫做“父类引用指向子类对象”(跟绕口令似的),或者叫“父类指针指向子类对象”,指的是定义一个父类的引用,而它实际指向的是子类创建的对象。功能上相当于子类的“向上转型”,或者“上溯对象”,
上面的语句也可以写成:


Animal a2 = new Animal();
Dog dog = new Dog();
a2 = dog;


将子类对象赋给父类的引用就是向上转型,Animal a2 = new Dog();中的new Dog()就是实例化一个没有名字的对象,然后转型给父类的引用a2,仅此而已。


--究竟有什么用途?
re:一般来说,一个对象实例创建完就定死了,比如dog,如果程序里的变量写dog的话,万一以后发生变化就要改代码了。那么事先就不写死dog,而是写父类Animal,那么以后用到Animal的地方,用dog实例,cat实例都可以取代,不用改实例名了。说玄乎一点,也就体现了面向对象“多态”的特性。


下面看一个很简单的例子,就更加明白了:


class Animal
{
private String type = "Animal";
public virtual void showLegs()
{
Console.WriteLine("This is an {0} , Animal always has legs",type);
}
}
class Dog : Animal
{
private String type = "Dog";
public override void showLegs()
{
Console.WriteLine("This is a {0} , Dog has four legs", type);
}
}
class Glede : Animal
{
private String type = "Glede";
public override void showLegs()
{
Console.WriteLine("This is a {0} , Glede has two legs",type);
}
}


class test
{
static void Main(string[] args)
{
Animal a1 = new Animal();
Animal a2 = new Dog();
Animal a3 = new Glede();
a1.showLegs();
a2.showLegs();
a3.showLegs();
Console.ReadLine();
}
}


结果:


This is an Animal , Animal always has legs
This is a Dog , Dog has four legs
This is a Glede , Glede has two legs


真正明白了这些,也就该接触设计模式领域了。


最后唠叨两句:


·因为a2,a3都是子类的对象,所以调用起来,也都是调用的子类的方法(当然前提是它们都override了父类方法,诸位可以试着把两个子类中的override替换成new,结果就完全不一样),有人把这叫做“关注对象原则”。


·向上转型是一定没有错的,就好比你说“狗是动物”是成立的,反之,向下转型就要注意了,你不能说“动物是狗”。


 class Program:B
    {
       
        static void Main(string[] args)
        { 
            //B b = new B();
            //A a = new A();
            //B c = new A();
            A d = new B();
            B b = new B();
            b.t();
            d.t();//错误访问不到
            //Console.WriteLine(A.strText);
            //Console.WriteLine(B.strText);
            Console.ReadKey();
        }
        
          //StringBuilder d = new StringBuilder();
          //  string s="ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss";
          //  for (int i = 0; i < 10000; i++)
          //  {
          //   d.Append(s);
          //  }
          //  Console.WriteLine("结果:{0}",d);
    
           
          // ArrayList arr=new ArrayList();
          
          //  for (int i = 0; i < 10000; i++)
          //  {
          //      arr.Add(s);
          //  }
          //  Console.WriteLine("arr 结果:" + arr);
          //  Console.ReadKey();
    }
    public class A
    {
        public static string strText;
        static A()
        {
            strText = "aaaaaaaaa";
            Console.WriteLine("A");


        }
    }
    public class B : A
    {
        static B()
        {
            strText = "bbbbbbbbbb";
            Console.WriteLine("B");
        }
        public  void t()
        { 
        
        }


    }