【java】父类声明子类实例化

本文深入解析多态性这一核心概念,阐述其工作原理,包括父类引用指向子类对象、方法覆盖、动态调用等,并解释变量为何不能被重写。

总结:

       对于多态,可以总结它为:

       1、使用父类类型的引用指向子类的对象;
       2、该引用只能调用父类中定义的方法和变量;
       3、如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法;(动态连接、动态调用)
       4、变量不能被重写(覆盖),“重写”的概念只针对方法,如果在子类中“重写”了父类中的变量,那么在编译时会报错。 

通俗理解:

       父类类型的引用指向子类的对象。父类只能调用自己的方法,但是如果自己的方法被子类覆盖了,那么调用的就是子类的。如果这个方法是子类独有的,那么父类类型的引用用不了。 简单的说,就是自己用自己的,儿子有父亲一样的,就用儿子的。省点钱是点。儿子独有的,父亲不会用,所以不能用 。

### 父类声明子类实例的实现方法 在C#中,父类声明子类实例是一种常见的面向对象编程实践,主要基于多态性机制。这种方式允许通过父类的引用访问子类的对象,从而实现更灵活的设计和代码复用。 #### 类型安全与多态性 使用父类声明子类实例的一个核心原因是多态性。父类的引用可以指向其任何子类的对象,而无需关心具体的实现细节。这种机制允许在运行时决定调用哪个类的方法,从而实现动态绑定。由于父类中定义的成员在子类中一定存在,因此通过父类引用访问子类对象是安全的。相反,如果尝试用子类引用指向父类对象,则可能会导致访问不存在的成员的问题,从而引发运行时错误 [^1]。 #### 构造函数与继承 在实例化子类时,无论是否显式指定,子类的构造函数总是会先调用父类的构造函数。这是为了确保父类的初始化逻辑在子类之前完成,保证对象的状态正确。如果父类有带参数的构造函数,子类必须通过 `base()` 调用相应的构造函数;如果父类没有显式定义构造函数,则默认有一个无参数的构造函数 [^4]。 #### 示例代码 以下是一个简单的示例,展示了如何在C#中使用父类声明并用子类实例化: ```csharp public class Parent { public virtual void OnOpen() { Console.WriteLine("Parent OnOpen"); } } public class Child : Parent { public override void OnOpen() { Console.WriteLine("Child OnOpen"); } } // 使用父类声明并用子类实例化 Parent scene = new Child(); scene.OnOpen(); // 输出 "Child OnOpen" ``` 在这个例子中,`Parent` 类定义了一个虚方法 `OnOpen`,而 `Child` 类重写了这个方法。通过父类 `Parent` 的引用 `scene`,我们实例化了 `Child` 类,并调用了 `OnOpen` 方法,实际执行的是 `Child` 类中的实现,体现了多态性的特点 [^2]。 #### 成员访问与强制类型转换 当使用父类引用指向子类对象时,只能通过该引用访问那些在父类中定义的成员。如果需要访问子类特有方法或属性,可以通过强制类型转换来实现。例如,在以下代码中,通过检查对象是否为特定子类的实例,然后将其转换为该子类的引用,以便访问其特有的成员 [^3]。 ```csharp public class Person { public string Name { get; set; } public int Age { get; set; } } public class Teacher : Person { public string MajorField { get; set; } public void Print() { Console.WriteLine($"Name: {Name}, Age: {Age}, MajorField: {MajorField}"); } } public class Student : Person { public string Grade { get; set; } public void Print() { Console.WriteLine($"Name: {Name}, Age: {Age}, Grade: {Grade}"); } } // 使用父类声明并用子类实例化 Person p = new Teacher(); p.Name = "周杰伦"; p.Age = 30; if (p is Teacher) { Teacher t = (Teacher)p; t.MajorField = "Java"; t.Print(); // 输出 "Name: 周杰伦, Age: 30, MajorField: Java" } else if (p is Student) { Student s = (Student)p; s.Grade = "大二"; s.Print(); } ``` 在这个例子中,`Person` 类是 `Teacher` 和 `Student` 类的基类。通过 `Person` 类的引用 `p`,我们实例化了 `Teacher` 类,并通过检查 `p` 是否为 `Teacher` 类的实例,将其转换为 `Teacher` 类的引用 `t`,进而访问 `Teacher` 类特有的 `MajorField` 属性和 `Print` 方法 [^3]。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值