JAVA面向对象之 方法重写、多态与抽象类的基础知识
文章目录
1. 方法重写
- 方法重写:当子类出现了和父类一模一样(方法名,参数列表,返回值)的一个方法,就会发生方法覆盖现象,子类的方法会覆盖父类方法;
- 子类对父类的不满意可以重写
- 当不想完全覆盖父类功能时,可以使用 super.方法名()//沿袭父类功能
public class Person {
int age;
String name;
public void sports(){
System.out.println("我爱运动");
}
public void study(){
System.out.println("我爱学习");
}
}
public class Student extends Person {
public void study(){
System.out.println("我爱学习敲Java");
}
}
public class Teacher extends Person{
public void study(){
@Override
super.study();//沿袭父类功能
System.out.println("我爱学习写教案");
}
}
public class Test {
public static void main(String[] args) {
Teacher t = new Teacher();
t.age=20;
t.name="老沈";
t.sports();
t.study();
System.out.println(t.name+t.age);
Student S = new Student();
S.age=20;
S.name="老沈";
S.sports();
S.study();
System.out.println(S.name+S.age);
}
}
/*
我爱运动
我爱学习 //沿袭父类功能
我爱学习写教案
老沈20
我爱运动
我爱学习敲Java
老沈20
*/
1.2 方法重写注意事项
- 子类不能重写父类私有方法,私有方法都不能继承,何谈重写?
- 子类重写父类方法时,方法的权限修饰符,要比父类的高或一样
- 构造方法不参与重写
- 静态方法不参与重写
- 父类final修饰的方法,子类不能重写
1.3 方法重载与方法重写区别
- 方法重载:允许一个类中,可以定义多个同名方法,知意他们的参数列表不同(形参个数,形参类型)
- 方法重写:发生在继承环境中,子类可以提供一个与父类一模一样的方法(方法名,形参列表,返回值),就会发生子类方法,覆盖父类方法现象。
入口类:只是作为程序入口,一般不会在入口类里面提供除了main方法之外的方法,只需要提供main方法即可,在main方法中,使用其他类
1.4 final关键字
- final:最终的,可以修饰变量,成员方法,类
- final:修饰变量,此方法就为常量
- final:修饰成员方法,此方法不能被重写,可以继承;
- final:修饰引用数据类型,指的是地址值不能再更改;
- final:修饰类,此类不能被继承;
- final:修饰引用数据类型,指的是地址值不能再更改
public static void main(String[] args) {
//final 修饰的基本数据类型,指的是变量的值,不可再更改了
final int num = 100;
//final 修饰的引用数据类型,指的是,这个地址值,不能再更改。
final Scanner scanner = new Scanner(System.in);
// scanner=new Scanner(System.in);
}
2. 多态
- 概念:指的是一种事物,在不同时刻所表现出的不同状态
例:
猫 他是猫类的一种 Cat cat=new cat();
猫 他是动物类的一种 Animal an=new cat()
多态的前提:
- 要有继承,如果没有继承,多态无从谈起;
- 要有方法重写,如果不重写,虽然语法不报错,但就失去了多态的意义;
- 父类引用指向子类对象 Animal an=new Cat()
2.1多态的好处
- 提高了复用性,提高了代码的维护性 扩展性(有利也有弊)
多态就是向上转型
**多态的形式访问成员变量:**编译看左边,运行也看左边,左边是父,右边是子类.
**多态的形式访问成员方法:**编译看左边,运行也看右边,左边是父,右边是子类,假如子没有被重写,就运行父的;
多态形式访问静态方法,访问的父类的静态方法,子类静态不需要被重写;
练习:孔子装爹
/*
孔子爹,是一个著名的Java讲师,张三,慕名前来,请孔子爹去他家里给他上课,孔子爹就去了
只留孔子一人在家,这个时候,李四也来孔子家里,请孔子爹去讲课。孔子爹不在家,
孔子不想失去这个学生,他就得乔装打扮一番,扮成他爹的模样,去给李四讲课,孔子只会讲论语。
讲完之后,孔子回到家里感觉,装爹他累了,他想做回他自己,然后愉快的玩了一把游戏。
*/
public class Kz extends KzDad{
int age=30;
public void teach(){
System.out.println("讲授论语");
}
public void playgame(){
System.out.println("玩游戏");
}
}
public class KzDad {
int age=60;
public void teach(){
System.out.println("讲授JAVA");
}
}
public class FouthLX {
public static void main(String[] args) {
KzDad kd =new Kz();
System.out.println(kd.age);
kd.teach();
System.out.println("+++++++++++++++++++++++++++++++++++++");
Kz K=(Kz) kd;
K.playgame();
}
}
2.2多态的弊端
- 不能直接访问子类特有的成员,如果要访问,需要向下转型: Son son=(son) f;
不能瞎转,父子之间转,子与子之间不能转;
//向下转型
public class MyTest {
public static void main(String[] args) {
Father f = new Son(); //多态,其实就是向上转型。
f.show();
//f.hehe();//不能直接访问子类特有的方法。
//向下转型
Son son = (Son) f;
son.hehe();
}
}
class Father {
public void show() {
System.out.println("fu show");
}
}
class Son extends Father {
@Override
public void show() {
System.out.println("zi show");
}
public void hehe() {
System.out.println("子类特有的方法");
}
}
练习2:多态传递
class A {
public void show() {
show2();
}
public void show2() {
System.out.println("我");
}
}
class B extends A {
public void show2() {
System.out.println("爱");
}
}
class C extends B {
public void show() {
super.show();
}
public void show2() {
System.out.println("你");
}
}
public class DuoTaiTest4 {
public static void main(String[] args) {
A a = new B();
a.show(); //爱
B b = new C();
b.show(); //你
}
}
练习3:多态构造方法,值传递,调用子类特有方法
public class Father {
int num = 100;
public Father() {
System.out.println("父类构造方法执行了");
}
public void show() {
System.out.println("fu show");
}
}
public class Son extends Father {
int price = 500;
public Son() {
System.out.println("子类构造方法执行了");
}
@Override
public void show() {
System.out.println("zi show");
}
public void hehe() {
System.out.println("hehe");
}
}
public class MyTest {
public static void main(String[] args) {
Father father = new Son();
System.out.println(father.num);
father.show();
Son son = (Son) father;
System.out.println(son.price);
son.hehe();
}
}
2.3 多态的内存解析
public class Father {
int num = 100;
public Father() {
System.out.println("父类构造方法执行了");
}
public void show() {
System.out.println("fu show");
}
}
public class Son extends Father {
int price = 500;
public Son() {
System.out.println("子类构造方法执行了");
}
@Override
public void show() {
System.out.println("zi show");
}
public void hehe() {
System.out.println("hehe");
}
}
public class MyTest {
public static void main(String[] args) {
Father father = new Son();
System.out.println(father.num);
father.show();
Son son = (Son) father;
System.out.println(son.price);
son.hehe();
}
}
- 上述代码在内存中是如何运行
![](https://pic.imgdb.cn/item/62510af3239250f7c5988f2f.png)
多态内存图分析
3.抽象类
- 一旦类中有抽象方法,那么类也就是抽象的
- abstract 抽象的,可以修饰类和方法
- 抽象方法,只需要给出所有子类的共性功能的声明,而不给出功能的具体实现,而是交由子类,按照自身的差异,去重写
- 父类的抽象方法,会强制子类必须重写.
- 抽象方法,强制子类重写
- 非抽象方法,就是让子类继承下去直接用,当然子类可以重写,但是不带有强制性.
- 抽象类里面既可以定义抽象方法,也可以定义非抽象方法
public abstract class Animal {
public abstract void eat();
public abstract void sleep();
public void show() {
System.out.println("fu show");
}
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sleep() {
System.out.println("猫白天睡觉");
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗爱吃骨头");
}
@Override
public void sleep() {
System.out.println("狗爱在狗窝里数据");
}
}
抽象类的特点
一但一个类有了抽象方法,此类必须为抽象类;
这个类的他没有定义抽象方法,可以把这个抽象类;
抽象类不能直接创建对象
抽象类不能直接创建对象,我们可以通过多态的方式,间接实例化这个抽象类;
作为抽象类的子类,他有两种选择:
1.子类必须重写抽象类中的所有抽象方法
2.你也变为抽象类:
抽象类中有构造方法. 作用:让子类可以通过多态的方式,简介实例化这个抽象类
@Override
public void eat() {
System.out.println(“狗爱吃骨头”);
}
@Override
public void sleep() {
System.out.println("狗爱在狗窝里数据");
}
}