Java基础知识
面向对象—多态
面向对象的三大特征:封装(类),继承(extends),多态
多态:指的是一种事物在不同时期,所表现的不同状态。
多态的前提:要有继承,如果没有继承,多态就无从谈起。多态要有方法重写,当然不重写对于语法上来说不报错,但是就失去了多态的意义。
案例程序分析1:
public class Mytest {
public static void main(String[] args) {
//面向对象的三大特征;封装(类) 继承(extends)多态
//多态:指的是一种事物,在不同时期,所表现出的不同状态。
//多态的前提:要有继承,如果没有继承多态就无从谈起。
//多态要有方法重写,当然不重写,语法上来说不报错,但是失去了多态的意义。
//父类引用指向子类对象。
Cat cat = new Cat();
cat.eat();
//多态:父类引用,指向子类对象
Animal an = new Cat();
an.eat();
}
}
class Animal{
public void eat(){
System.out.println("吃饭");
}
}
class Cat extends Animal{
@Override
public void eat() {
//super.eat();
System.out.println("猫吃小鱼干");
}
}
1.多态:父类引用指向子类对象,采用多态的形式,去访问成员变量,访问的是父类。
成员变量:编译看左边,运行看左边。
2.多态形式去访问构造方法:创建子类对象的时候,会调用父类的构造方法,对父类的数据进行初始化。
***用多态的时候,先调用父类的构造方法,再调用子类的构造方法***。
3.多态的形式,访问成员方法的特点,如果子类没有重写父类的方法,就以父类的方法为准,如果子类重写了父类的方 法,那么运行时,就以子类重写过的为准。
成员方法:编译看左边,运行看右边。
案例程序分析2:
public class Mytest {
public static void main(String[] args) {
//多态:父类引用,指向子类对象
Fu an = new Zi();
//int num = ((Zi) an).num;
System.out.println(an.num);//100 采用多态的形式,去访问成员变量,访问的是父类的成员变量
System.out.println(((Zi) an).num);//200
System.out.println("-------------");
//多态的形式,访问成员方法的特点,
// 如果子类没有重写父类的方法,就以父类的方法为准,
// 如果子类重写了父类的方法,那么运行时,会以子类重写过后的为准。
an.show();
//静态方法
an.fujingtai();
Fu.fujingtai();
}
}
class Fu{
int num=100;
public Fu(){
System.out.println("父类的构造方法执行了");//1
}
public void show(){
System.out.println("父类的show方法执行了");
}
public static void fujingtai(){
System.out.println("父类的静态方法执行了");//4.5
}
}
class Zi extends Fu{
int num=200;
int aa=500;
public Zi(){
System.out.println("子类的构造方法执行了");//2
}
@Override
public void show() {
//super.show();
System.out.println("子类的show方法执行了");//3
}
}
多态的好处:多态的好处:提高代码的复用性a:提高了代码的维护性(继承保证)
b:提高了代码的扩展性(由多态保证)
案例程序分析3:
public class Mytest {
public static void main(String[] args) {
//多态的好处:提高代码的复用性a:提高了代码的维护性(继承保证)
// b:提高了代码的扩展性(由多态保证)
Cat cat = new Cat();
MyUtils.testEat(cat);
Dog dog = new Dog();
MyUtils.testEat(dog);
Tiger tiger = new Tiger();
MyUtils.testEat(tiger);
Rabbit rabbit = new Rabbit();
MyUtils.testEat(rabbit);
Panda panda = new Panda();
MyUtils.testEat(panda);
}
}
class Animal{
public void eat(){
System.out.println("吃饭");
}
}
class Cat extends Animal{
@Override
public void eat() {
//super.eat();
System.out.println("猫吃老鼠");
}
}
class Dog extends Animal{
@Override
public void eat() {
//super.eat();
System.out.println("狗吃骨头");
}
}
class Panda extends Animal{
@Override
public void eat() {
//super.eat();
System.out.println("熊猫吃竹子");
}
}
class Rabbit extends Animal{
@Override
public void eat() {
//super.eat();
System.out.println("小白兔吃草");
}
}
class Tiger extends Animal{
@Override
public void eat() {
//super.eat();
System.out.println("老虎吃肉");
}
}
----------------------------------------------
public class MyUtils {
//如果你通过方法重载,来设计这个工具类。
// 扩展性不好。因为没增加一种动物。你就得在工具类中提供一个重载方法。
//私有构造
private MyUtils(){
}
public static void testEat(Animal an){
//Animal an=new Cat()
//Animal an=dog//
// Animal an = tiger
an.eat();
}
/* public static void testEat(Cat cat) {
cat.eat();
}
public static void testEat(Dog dog) {
dog.eat();
}
public static void testEat(Tiger tiger) {
tiger.eat();
}
public static void testEat(Rabbit rabbit) {
rabbit.eat();
}*/
}
向下转型
多态的弊端:不能直接调用子类特有的功能。
多态的形式不能直接调用子类特有的功能,如果要调用子类特有的功能,即向下转型。
向上转型:把子类型,转换成父类型。多态就是向上转型。
案例程序分析4:
public class Mytest {
public static void main(String[] args) {
//多态的弊端,不能直接调用子类特有的功能
Fu fu = new Zi();
fu.show();
//多态的形式不能调用子类特有的功能
//如果我们要调用子类特有的功能,需要采用向下转型。
Zi zi=(Zi) fu;//向下转型
zi.method();
//向上转型:把子类型,转换成父类型。多态就是向上转型.
}
}
class Fu{
public void show(){
System.out.println("父类的show方法");
}
}
class Zi extends Fu{
@Override
public void show() {
//super.show();
System.out.println("我重写了父类的show方法");
}
public void method(){
System.out.println("这是子类特有的method方法");
}
}
案例程序分析5:
public class Mytest {
public static void main(String[] args) {
Animal an = new Cat();//多态,向上转型
an.eat();
Cat cat = (Cat) an;//向下转型
cat.catchMouse();
Animal an1 = new Dog();//多态,向上转型
an1.eat();
Dog dog = (Dog) an1;//向下转型
dog.lookDoor();
}
}
class Animal{
public void eat(){
System.out.println("吃饭");
}
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
public void lookDoor(){
System.out.println("狗看门");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
案例程序分析6:
public class MyTest {
public static void main(String[] args) {
Father father = new Son();//采用多态的形式去访问成员变量,访问的是父类
System.out.println(father.num); //100
father.show();
//访问子类的成员变量,访问子类特有的功能,采用向下转型
Son son= (Son) father;
System.out.println(son.num); //50
son.hehe();
}
}
class Father{
int num=100;
public void show(){
System.out.println("父类 show 方法");
}
}
class Son extends Father{
int num=50;
@Override
public void show() {
System.out.println("子类 show 方法");
}
public void hehe(){
System.out.println("子类特有的方法");
}
}
多态内存图:
练习题:案例程序分析7:
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();//你
}
}
抽象类
abstract关键字:
抽象类:抽象出来,不需要给出功能的具体实现,而是由子类根据自身的差异性,对这个功能进行具体的实现。
一旦一个类中,有了抽象方法该类必须为抽象类。抽象类:不能直接创建对象。
父类中的抽象方法,是强制子类必须重写:
abstract class Animal{
public abstract void eat();——————>父类给个声明
}
案例程序分析8:
public class Mytest {
public static void main(String[] args) {
//抽象类,不能直接创建对象
Animal cat = new Cat();
cat.eat();
cat.sleep();
Animal dog = new Dog();
dog.eat();
dog.sleep();
}
}
abstract class Animal{
//抽象的父类,在父类中只需要给出一个声明,由子类去重写父类的方法,实现需要的功能。
public abstract void eat();
public abstract void sleep();
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫不喜欢吃饭,他喜欢捉老鼠");
}
@Override
public void sleep() {
System.out.println("猫喜欢在白天睡觉,晚上出来活动");
}
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗不喜欢吃饭,它喜欢吃骨头");
}
@Override
public void sleep() {
System.out.println("狗整天都在睡觉");
}
}
父类把所有子类的共享内容向上抽取出来,但是父类不知道子类对于共性功能的具体实现,所以父类只需要给出功能的声明,而不需要给出功能的具体实现,那功能的具体实现,应该交给子类按照自身的需求和差异,去做具体的实现。
一个抽象类中可以不用定义抽象方法。
一旦一个类中定义了抽象方法,此类必须为抽象类
抽象类的子类:要么是抽象类,要么重写抽象类中的所有抽象方法
案例程序分析9:
public class Mytest {
public static void main(String[] args) {
EE ee = new EE();
ee.BB();
ee.DD();
ee.show();
}
}
abstract class BB{
public abstract void show();
public abstract void BB();
}
abstract class DD extends BB{
public abstract void DD();
}
class EE extends DD{
@Override
public void show() {
System.out.println("继承父类的show方法");
}
@Override
public void BB() {
System.out.println("继承父类的BB方法");
}
@Override
public void DD() {
System.out.println("继承父类的DD方法");
}
}