父类和子类转换浅谈篇

测试一
父类:
public class Supclass
{
    public void print()
     {
        System.out.println("this is 父类print()方法"+"——此时对象"+this.toString());
     }
}

子类:
public class Subclass extends Supclass
{
    public static void main(String[] args)
     {
        Supclass sup=new Subclass();
        sup.print();
        System.out.println("此时对象"+sup.toString());
     }
}

   结果:this is 父类print()方法——此时对象是Subclass@126b249
         此时对象是Subclass@126b249
   说明:
    Supclass sup=new Subclass();
    虽然声明的对象是父类对象,但实际的内存空间是子类对象的。
    继承父类的方法public void print()被调用,输出的是子类对象名字解析。

结论:编译时声明的对象是父类对象,但运行时却是子类对象.子类没有重写父类的方法,则此   时的对象调用继承父类的方法。

测试二
   父类:
public class Supclass
{
    public void print()
     {
        System.out.println("this is 父类print()方法"+"——此时对象"+this.toString());
     }
}

   子类:
public class Subclass extends Supclass
{
        public void print()
     {
        System.out.println("this is 子类print()方法"+"——此时对象"+this.toString());
     }
    public static void main(String[] args)
     {
        Supclass sup=new Subclass();
        sup.print();
        System.out.println("此时对象"+sup.toString());
     }
}

    结果:this is 子类print()方法——此时对象是Subclass@126b249
          此时对象是Subclass@126b249
    说明:
    我在上个例子的基础上,重写了父类的print()方法,此时的调用的是子类的print()方法。

结论:在上个例子结论的基础上,我得到了一个结论:此时对象运行时确实子类对象,如果子类没有从写父类的方法,
       则此时的对象调用继承父类的方法;否则,此时的对象调用子类方法.

问题: 我们是不是可以从上面的测试得到的这样结论: 将子类对象赋值给父类对象(即Supclass sup=new Subclass()),
        我们得到的就是子类对象,即sup就是子类对象??????
测试三
   父类:
public class Supclass
{
        protected String className="父类属性";
    public void print()
     {
        System.out.println("this is 父类print()方法"+"——此时对象"+this.toString());
     }
}

   子类:
public class Subclass extends Supclass
{       
        protected String className="子类属性";
        public void print()
     {
        System.out.println("this is 子类print()方法"+"——此时对象"+this.toString());
     }
    public static void main(String[] args)
     {
        Supclass sup=new Subclass();
        System.out.println("此时的属性时:"+sup.className);
     }
}

   结果:此时的属性时:父类属性

   说明:我在第一个测试的基础上,给父类添了一个属性className,在子类重写了这个属性.
         但我输出此时对象的属性时,却是父类的属性.
   结论: 将子类对象赋值给父类对象,方法和属性和我们正统的继承关系很不一样.
   问题:
        此时对象究竟是子类对象,还是父类对象?

   开始推测:  
       我在推测之前有几点须声明:
       1.当我们new一个子类对象时,父类对象的构造函数同时也被执行,即父类的一些必要信息和子类对象共占一个内存空间,
         当我们方法重写时,于是我们就能使用super这个指代父类的对象.

       2.java中对象并不是完全的面向对象思想做的,即不是把一个对象的属性和方法同时封装到对象中.
         而是对象有自己的属性,方法却是引用类中的方法,可以说它是把属性和类中方法的引用封装到对象中.
         于是对象调用的方法不是自己的方法,而是类中方法.至于java为什么要这样做,我就不知道了.

       3.当对象被加载到内存时,类先被加载到内存中,此后类应是一只留在内存中.至于类什么时候从内存中消失,我也不知道.
          我想java一定有自己的回收机制,就像回收对象一样.

       4.编译和与运行是完全不同的事.编译时主要做的是声明对象的类型,分配属性,检查语法错误等
         运行时做的是,将对象加载内存(一般用new,反射也常用), 运行代码执行功能等.
      
       5.若是读者您和我在这几点没有产生共鸣的话,或者说我们在这几点没用相同的认识的话,你会觉得我在胡说.
         也许你会觉得我的专家分太低,就觉得我的可信程度就低.但我想说的是学不分先后,达者为先.
         呵呵,我已准备好将我的专家分变为负值了,不胡扯了,我们继续.

      推测:
        1.当我们编译Supclass sup=new Subclass()时,sup对象被声明为Supclass类,于是sup对象的属性便是父类对象的属性的值,
          它是编译时被确定好的.(声明4,可以对这段进行解释).这段话可以对测试三进行解释,即为什么此时对象的属性是父类对象的属性.

        2.当我们运行Supclass sup=new Subclass()时,此时sup对象的内存空间是子类对象的内存空间(声明4,可以对这段进行解释),
          注意此时sup对象的内存空间由两部分组成父类的一些必要信息和子类对象信息(声明1,可以对这段进行解释).
          当我们不重写父类的方法时,由于此时内存空间已有父类的一些必要信息,所以继承父类的方法public void print()当然能被调用。
          这段话可以对测试一进行解释.

        3.接着2继续,若我们重写父类的方法时,由于sup对象的内存空间是子类对象的内存空间,子类的方法public void print()已被加载到内存中.
          所以我们调用的是子类的方法public void print();如果你需要调用父类的被重写方法,需要用super.
          这段话可以对测试二进行解释.
      总结:
          以下纯是个人观点:
          将子类对象赋值给父类对象,所得到对象是这样的一个对象:
          它是一个编译是为父类对象,但运行却是一个子类对象,具体特征如下.
          1.被声明为父类对象
          2.拥有父类属性
          3.占用子类的内存空间
          4.子类方法覆盖父类的方法时,此时对象调用的是子类的方法;否则,自动调用继承父类的方法.
          5.我人认为这个对象既不是父类对象,也不是子类对象.当我们用到它的方法时,
            我便把它看成子类对象;若用到它的属性时,我把它看成父类对象.
            它是一个占用父类属性,而使用子类方法的对象.至于到底是什么对象,我认为还是得根据声明来,它应算是父类对象,但拥有子类方法.

<think>我们讨论的是Python中父类子类之间的类型转换。在面向对象编程中,类型转换通常指的是将一个对象从一种类型转换为另一种类型,特别是在继承体系中,我们有时需要将父类对象转换子类对象,或者反过来。然而,在Python中,由于动态类型的特点,这种转换通常不是直接进行的,而是通过设计模式或者特定的方法来实现。在Python中,子类实例可以被视为父类类型(这是多态的体现),因此将子类实例传递给期望父类类型的函数或方法时,不需要显式转换。但是,反过来,将父类实例转换子类实例通常是不安全的,因为父类实例可能没有子类特有的属性方法。然而,有时候我们确实需要将一个父类对象转换子类对象,前提是我们知道这个父类对象实际上是由子类实例化而来的(例如,我们通过工厂方法创建了一个子类对象,但以父类类型返回)。在这种情况下,我们可以通过修改对象的__class__属性或者使用类型构造器来实现。但要注意,这种做法通常不被推荐,因为它可能破坏面向对象的设计原则,并且容易出错。下面我们讨论几种可能的方法:方法1:直接修改__class__属性(不推荐,因为可能造成状态不一致)如果我们有一个父类对象,但实际上它是子类的实例(例如,由于某些原因被强制转换成了父类),我们可以尝试将它的__class__设置为子类。但是,这要求该对象已经具有子类的所有属性,否则在调用子类方法时可能会出错。方法2:使用子类的构造方法我们可以创建一个新的子类对象,并将父类对象的属性复制过去。这种方法比较安全,但需要额外的复制操作。方法3:在父类中提供转换方法可以在父类中定义一个方法,该方法返回一个子类实例,将父类的属性复制过去。这需要父类知道子类的存在,可能会破坏封装。方法4:使用类型转换函数我们可以编写一个转换函数,接受父类对象子类类型,然后创建一个新的子类对象,复制父类对象的属性。下面我们通过代码示例来说明方法2方法4。假设我们有一个父类Animal一个子类Dog:</think>在Python中,父类子类之间的类型转换通常通过**显式类型转换**或**设计模式**实现。由于Python是动态类型语言,直接类型转换不像静态语言那样严格,但需注意对象实际类型属性兼容性。以下是三种常用方法: --- ### 1. **显式构造子类对象** 通过父类对象的数据构造新的子类实例(最安全): ```python class Animal: def __init__(self, name): self.name = name class Dog(Animal): def __init__(self, name, breed): super().__init__(name) self.breed = breed # 父类实例 animal = Animal("Buddy") # 转换子类:用父类数据构造新Dog对象 dog = Dog(animal.name, "Unknown Breed") # 补充子类特有属性 print(dog.breed) # 输出: Unknown Breed ``` **适用场景**:当需要添加子类特有属性时。 --- ### 2. **动态修改对象类型(谨慎使用)** 直接修改对象的`__class__`属性(风险较高): ```python animal = Animal("Buddy") animal.__class__ = Dog # 修改类型为子类 animal.breed = "Labrador" # 必须补充子类属性 print(isinstance(animal, Dog)) # 输出: True ``` **注意**: - 需手动补全子类特有属性(如`breed`),否则访问时抛`AttributeError` - 仅当对象实际是子类实例时安全(如通过工厂函数返回的父类引用) --- ### 3. **类型转换方法** 在父类中定义转换接口(推荐面向对象设计): ```python class Animal: def __init__(self, name): self.name = name def to_dog(self, breed): return Dog(self.name, breed) animal = Animal("Buddy") dog = animal.to_dog("Golden Retriever") print(dog.breed) # 输出: Golden Retriever ``` --- ### 关键注意事项 1. **类型兼容性** - 子类父类:自动向上转型(安全) ```python dog = Dog("Max", "Husky") animal: Animal = dog # 隐式转换 ``` - 父类子类:需显式操作(可能丢失数据) 2. **类型检查** 使用`isinstance()`或`type()`验证对象类型: ```python if isinstance(animal, Dog): print("可安全转换") ``` 3. **设计原则** 优先通过**多态**或**工厂模式**避免强制转换,如: ```python class Animal: def speak(self): raise NotImplementedError # 强制子类实现 ``` --- ### 应用场景示例 - **反序列化**:将通用数据对象转换为具体子类 - **插件系统**:父类接口动态加载子类实现 - **数据处理**:将基础数据容器转换为特化子类容器 > 引用参考:Python官方文档指出修改`__class__`可能破坏内部一致性[^1],而显式构造是更安全的转换方式[^2]。多态设计可减少类型转换需求[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值