面向对象(多态表现一、方法重写、强制类型转换的情况)
面向对象(多态、方法重写、强制类型转换的情况)
多态注意⚠️
1.明确概念
多态是方法的多态,属性没有多态
2.多态存在条件:
有继承关系
public class Cat extends Animal{}<父类引用>指向<子类对象>例如:
Animal animal1 =new Cat();
3.多态的体现
⚠️:多态的体现就在于:
1.<父类引用>指向<子类对象>:也就是类型父类化,则该对象可以描述父类下的任何一个子类,我们可以清楚的看到这样写法的优势.把不同的子类对象都当作父类来看,利用子类对父类方法的重写,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化
2.多态应用之方法参数列表写成父类,可以在设计时合并多个子类参数的方法,并且后期具有拓展性
3.方法的返回类型使用父类,经典应用: 简单工厂
重写
前提:有继承关系
对父类方法的重写.如果没重写就默认调用父类自己的方法.如果子类重写可父类的方法,那么在调用时,就会覆盖父类的方法.(这里可以转换下思想,如果你把对象类型升级到了父类的目的就是为了屏蔽不同子类对象之间的差异,写出通用的代码,所以最开始就应该在父类中把通用的功能定义好,通过子类的重写达到描写不同的子类对象时都会出现不同的效果,而对于不同子类有属于自己的特定的方法,那么这种情况只有通过强转了,但是抛开这种情况不谈,对于通用的方法可以在父类中进行定义,子类根据需求选择是否重写
小结:1.方法重写可以减少强转的步骤(运行时子类重写的方法可以覆盖父类中被重写方法),简化代码 2.子类能够根据需要实现父类的方法
强制类型转换的情况
⚠️:如果Animal animal1 =new Cat()中对象animal想要调用Cat()类中特有的方法必须强转为子类Cat(),如果是父类中也有这个方法,Cat类对其重写了就不需要强转了,子类的方法会覆盖父类的方法.(以下内容会继续阐述这个原理)
对象animal想要调用Cat()类中**特有**的方法
Animal animal1 =new Cat();
强制类型转换前一定要进行类型判断(
if(animall instanceof Cat()){
((Cat)animail).sikll();
}
⚠️强制类型转换的本质就是把编译时类型从父类改成它真正的子类类型
3.其中父类方法无法被重写的情况
1.static 方法 属于类 它不属于实例
2.final 常量;
3.private 方法;
4.对象可以访问的属性和方法是由它的编译时类型来决定的!!!
5子类继承父类,如果使用多态,编译时类型写成父类,则子类只能访问到父类的公共方法,无法访问其自己的特有方法,但是可以通过强制类型转换解决!
例如:Animal animal1 =new Cat();在编译时我创建了Animal类的对象animal1,来描述子类这样做有什么优点?有什么缺点?
解答:
优点: 类型父类化,则该对象可以描述父类下的任何一个子类,包括后期的拓展 缺点: 它只能访问父类的成员,无法访问子类特有的成员 简单来说:当父类引用变量指向子类对象后(多态),只能使用父类已声明的方法,但方法如果被重写会执行子类的方法,如果方法未被重写那么将执行父类的方法。当父类引用变量指向子类对象后(多态)如何才可以访问子类自己的方法呢,我们可以通过以下方法实现!!!!!
强制类型转换类解决该问题,强制类型转换的本质就是把编译时类型从父类改成它真正的子类类型 强制类型转换前一定要进行类型判断(instanceof),否则可能会出现类型转换异常:java.lang.ClassCastException Animal animal1 =new Cat(); if(animall instanceof Cat()){ ((Cat)animail).sikll(); }
tips:
对象能执行哪些方法主要看对象左边的类型和右边关系不大
重写注意⚠️
1.需要有继承关系,子类重写父类的方法!
2.方法名必须相同
3.参数列表必须相同
4.修饰符可以不同:范围可以扩大但不能缩小:
public > protected > Default > private
5.抛出的异常:范围,可以被缩小,但不能扩大:
ClassNotFoundExcption--->Exception(大)
为什么需要重写?
1.父类的功能:子类不一定需要,或者不一定满足!
<父类引用>指向<子类对象>(多态表现一)以及方法重写的详解:
阅读上面的多态知识点总结后可能还是搞不懂多态的表现之一 <父类引用>指向<子类对象>为什么要这样做,我在这里再详细的说一下,最好的做法就是在代码中练习寻找答案,我先举一个例子把,我们跟这个例子的思路来理解面向对象编程为什么需要多态,并且将封装,继承,方法重写全部串起来讲!!!!!
例如我们写一个银行业务系统,那么在开户这个业务中我们提出有两种情况,第一种办理储蓄卡,第二种我们办理信用卡.我们知道这两种卡的性质有相同点,也有不同的点,先从相同的点来说如果我需要同时办理两张卡那么我们都需要用到个人信息:名字、身份证号码、联系方式这样的基本信息.然后由于他们两张卡的用途不同所以各自也就具有不同的方法
当我们清楚它的相同点和不同点之后,我们开始进行具体代码的编写,首先我们结合一下前面学到的封装和继承的知识,我们可以先写一个Account类将他们都需要用到的属性都写在这里面,也就是个人信息:名字、身份证号码、联系方式.、可能还有一些都会用到的方法,比如查询账户余额这样的功能,那么我们可以把这些都写在父类Account,然后通过继承,储蓄卡和信用卡类都可以对其访问了.大概的代码如下
public class Accont {
long id;
String password;
String name;
String personID;
String email;
double balance;
public Accont() {
}
public Accont(long id, String password, String name, String personID, String email) {
this.id = id;
this.password = password;
this.name = name;
this.personID = personID;
this.email = email;
balance = 0.0;
}
public void findbalance(){
}
get....
set.....
}
Account类写好以后,我们可以看出这里运用到了面向对象中封装的知识点,我们现在通过面向对象中继承的知识点,将储蓄卡类以及信用卡类继承Account,然后就可以通过super关键字调用父类中已经存在的某个构造方法对父类的属性进行操作,那么到这里都只运用到了封装,继承这两个知识点.
定义完Account类并且将储蓄卡类以及信用卡类都继承以后,我们可以思考一下对于储蓄卡和信用卡的用途不同自然他们之间的业务使用的具体方法也是不同的,那么这里我们就要引出#方法重写#这个概念,我们先看下面的代码:
public void findbalance(){
}
由于储蓄卡类以及信用卡类都继承了Account类,自然它们都具有这个方法,但是结合实际储蓄卡使用这个方法是用来查询自己的余额的,但是信用卡使用这个方法是用来查询自己的借款额度的,那么我们就不能继续用这个父类的方法了,有什么办法呢?这个时候就需要方法重写了,子类根据自己具体的需求,对父类的方法进行重写来满足自己的需求!
到现在我们运用了封装、继承、方法的重写、还是没有运用多态,现在我们来思考一个问题
联系实际的生活,如果一个人经常的使用信用卡,并且信用极好,按时还款,那么银行是不是会考虑对他的信用卡进行升级呢?最初他就是一个最低级别的信用卡额度就3000块钱并且只能用于特定的场所消费,经过一段时间银行决定将它的信用卡级别升级到vip信用卡,可以在任意的场所进行消费并且可以取现金使用,那么对于我们编程人员来说,vip信用卡和最低级别的信用卡在功能上肯定是不同的吧,所以我在最初研发的时候肯定需要写一个vip信用卡的类.
在后端如果在创建账户的时候,我们是以最低信用卡类 用户 1 = new 最低信用卡类()这样的方式来写的话,我们相当于把这个账号写死了,如果后期我们想要对这个用户1的信用卡进行升级,升级到vip信用卡,我们该怎么办呢?总不可能为了他这个人,把所有最低信用卡类的方法全部删除重写吧?,所以在创建账户的时候,我们最好的方式就是以Account 用户1 =new 最低信用卡类这样来写,也就是类型父类化,则该对象可以描述父类下的任何一个子类,我们可以清楚的看到这样写法的优势.
在后期我们想要对这个用户1升级就只需要将这个用户1对象描述为vip类Account 用户1 =new vip信用卡类,这相比于前面那种做法是不是优势非常大,这样做不仅有利于后期的扩展,还提高了代码的可维护性.
把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化
总结
封装:增加安全性能
继承:增大代码复用率
多态:方便后期的扩展,提高可维护性
方法的重写:满足具体业务的需求

浙公网安备 33010602011771号