(7.19java学习日记)
7.19日 java基础p 436 - p460
学习时间:7 小时
关键词: OOP extends继承 方法覆盖/重写 多态 运算符instanceof
面向对象中的继承:
extends 只可以继承一个类,不支持多继承,继承之后,父类中用的方法子类都会有。(构造方法除外)子类中无法直接访问父类的私有属性。如果没有extends的话,默认继承Object类
作用:
1.代码的复用
2.因为有了继承,所以才有后面的方法覆盖和多态机制
System.out.println()中,System.out指向的是一个对象,out是静态的变量
方法覆盖:在子类中重新写一个方法将父类的方法进行覆盖,比如重新写一个toString,如果是原来的toString输出的是 类名@十六进制
我们可以重写,让他输出对象的值
方法重载:在一个类中,方法名相同,方法参数的个数或类型不同,通过个数和类型的不同来区分不同的函数
方法重写:
在Java程序中,类的继承关系可以产生一个子类,子类继承父类,它具备了父类所有的特征,继承了父类所有的方法和变量。
子类可以定义新的特征,当子类需要修改父类的一些方法进行扩展,增大功能,程序设计者常常把这样的一种操作方法称为重写,也叫称为覆写或覆盖。
重写体现了Java优越性,重写是建立在继承关系上,它使语言结构更加丰富。在Java中的继承中,子类既可以隐藏和访问父类的方法,也可以覆盖继承父类的方法。
在Java中覆盖继承父类的方法就是通过方法的重写来实现的。所谓方法的重写是指子类中的方法与父类中继承的方法有完全相同的返回值类型、方法名、参数个数以及参数类型。
这样,就可以实现对父类方法的覆盖。如果子类将父类中的方法重写了,调用的时候肯定是调用被重写过的方法,那么如果现在一定要调用父类中的方法该怎么办呢?
此时,通过使用super关键就可以实现这个功能,super关键字可以从子类访问父类中的内容,如果要访问被重写过的方法,使用“super.方法名(参数列表)”的形式调用。
如果要使用super关键字不一定非要在方法重写之后使用,也可以明确地表示某个方法是从父类中继承而来的。使用super只是更加明确的说,要从父类中查找,就不在子类查找了。
多态:
多种状态,编译和运行的有两个不同的状态
编译期:静态绑定
运行期:动态绑定
例如 Animal a = new Cat()
编译器发现a的类型是Animal 但是堆内存中真实的对象是Cat
多态的经典类型:父类型的引用指向子类型的对象
向上转型 子—>父
父类 s = new 子类()
此时类型是父类,但是实际堆中的内存的对象是子类
静态绑定的时候是以父类类型,但是动态执行的时候是子类
如果此时调用了一个子类重写的方法,那么此时运行便是子类的方法。
向下转型: 父---->子
语法:Bird b = (Bird)x;
当父类需要调用子类的特有的方法的时候,需要向下转型
具有风险性,强转后可能会导致:静态绑定可以通过,但是对象里面其实没有这个方法,因此运行时候会出现:类型转换异常java.lang.ClassCastException(非常经典,和空指针异常一样)
所以一般需要用运算符instanceof来判断,你到底是不是这个东西语法为:(c instanceof Cat)只可能为ture或者是false,所以此处需要使用if(c instanceof Cat)来判断如果是的话就执行。这个是为了规范,以及方便其他程序员调用这个方法,不会运行报错。
多态开发中的作用:
1.降低程序的耦合度,提升程序的扩展力
高手开发的时候,除了功能的实现,还要考虑扩展性,OCP,开闭原则,代码修改的越少越好,修改的越多,稳定性越差。
通过一个例子来看多态的作用:
//主人类
public class Master {
public void feed(Pet pet) {
pet.eat();
}
}
//宠物类 此处的宠物也可以分开写,但是为了方便就都放在一起了
public class Pet {
public void eat() {
}
}
class Dog extends Pet{
public void eat() {
System.out.println("狗狗在吃骨头,真香!!!");
}
}
class Cat extends Pet{
public void eat() {
System.out.println("猫咪在吃鱼,真美味!!!");
}
}
class YingWu extends Pet{
public void eat() {
System.out.println("鹦鹉吃饲料,哈哈哈!!!");
}
}
//最后写一个测试类
public class Test {
public static void main(String[] args) {
Master zhangsan = new Master();
Dog zangAo = new Dog();
zhangsan.feed(zangAo);
Cat xiaoHua = new Cat();
zhangsan.feed(xiaoHua);
YingWu duoZui = new YingWu();
zhangsan.feed(duoZui);
}
}
最后运行成功截图:
其中这里来看,子类的Cat,Dog,YingWu都继承了Pet方法,当调用的时候,便是多态,相当于Pet pet = new Dog(),因此你调用哪一个宠物类,那么就会输出哪一个宠物的eat方法,这样来写的话,Master类便不用修改,如果有一个新的宠物类加入的话,只需要加一个类,然后重写eat方法即可。对扩展开放,对修改关闭,符合开闭原则OCP
面向对象的三大特征:
封装,继承,多态 真是一环扣一环
有了封装,有了这种整体的概念之后,对象和对象之间产生了继承
有了继承之后,才有了方法的覆盖和多态。
方法重写之后,更好用到多态,如果使用一个新的方法,那么只能调用这一个单独的方法。