第十天多态继承补充和final

编程入门 行业动态 更新时间:2024-10-11 05:29:05

<a href=https://www.elefans.com/category/jswz/34/1730522.html style=第十天多态继承补充和final"/>

第十天多态继承补充和final

继承补充:

方法重写的注意事项:

1、父类中私有的方法不能被重写

2、子类重写父类的方法时候,访问权限不能更低

要么子类重写的方法访问权限比父类的访问权限要高或者一样

建议:以后子类重写父类的方法的时候,权限修饰符写一样就不会发生这样的问题。

3、父类中静态的方法不能被重写,也就是说不能被Override修饰,因为静态的是属于类本身的东西。

class OldPhone {private String name;public void call(String name) {System.out.println("打电话给" + name);}public static void play() {//当这个方法是静态时后面子方法便无法重写System.out.println("玩俄罗斯方块");}
}class NewPhone extends OldPhone {@Overridepublic void call(String name) {System.out.println("看抖音");}public static void play(){System.out.println("打王者");}}public class ExtendsDemo1 {public static void main(String[] args) {NewPhone newPhone=new NewPhone();newPhone.call("小王");newPhone.play();}
}第二个

class A {static int a = 10;//将父类中的静态成员看作一个全局共享的,被所有的子类共享public static void fun() {System.out.println("hello");}
}class B extends A {public void fun2() {a = 200;System.out.println(a);}public static void fun() {System.out.println("world");}
}public class ExtendsDemo2 {public static void main(String[] args) {B b=new B();System.out.println(b.a);b.fun();b.fun2();//当调用完这个后改变了a的值为200导致后面的调用a变成了200System.out.println(b.a);System.out.println(A.a);}
}

final的特点:

final:最终的的意思。它可以修饰类,成员变量,成员方法

特点:

1、修饰类,类不能被继承

2、修饰成员变量,变量变常量,并且只能赋值一次,在构造方法完毕之前赋值即可。

常量:

字面值常量

自定义常量:被final修饰变量变成自定义常量

3、final修饰成员方法:方法不能被重写

class Fu2 {int num = 10;final int num2 = 20;
}class Zi2 extends Fu2 {public void show() {num = 100;System.out.println(num);
//        num2=300;//报错无法为num2赋值System.out.println(num2);}
}public class FinalDemo {public static void main(String[] args) {Zi2 zi2 = new Zi2();zi2.show();}
}

final修饰局部变量

1、在方法内部,修饰基本数据类型的变量,变量值只能赋值一次,不能发生改变

2、final修饰引用数据类型的变量呢?

引用的地址值不可以发生改变,但是该对象的堆内存中的值是可以发生改变的。

class Student {int  age = 10;
}public class FinalDemo2 {public static void main(String[] args) {int x = 100;x = 300;System.out.println(x);final int y = 200;//        y = 400; //无法为最终变量y分配值System.out.println(y);Student student=new Student();System.out.println(student.age);final Student s2=new Student();System.out.println(s2.age);s2.age=202;System.out.println(s2.age);System.out.println("===========");//        s2 = new Student(); //无法为最终变量s2分配值}
}

有些时候,我们不想让子类覆盖重写父类中的方法或者功能,只能让子类去使用。

那怎么办呢?

针对这个情况,java提供了一个关键字:final

final:最终的意思。可以修饰类,成员变量,成员方法。

class Fu{public final void show(){System.out.println("这是父类中的show方法");}
}class Zi extends Fu{
//    @Override
//    public void show(){
//        System.out.println("这是子类中的show方法");
//    }}public class ZiDemo {public static void main(String[] args) {Zi zi = new Zi();zi.show();}
}

多态:

多态:某一事物,在不同时刻表现出来的不同状态

举例:

水:

固态、液态、气态

固态的水是水、液态的水也是水、气态的水也是水

水果:

波罗蜜、香蕉、榴莲

波罗蜜是水果、香蕉是水果、榴莲是水果

水果是波罗蜜。// 反过来说是有问题的

动物:

狗、虎、猫、大象

狗是动物,这么说是没问题的

动物是狗,这么说是不可以。

通过观察例子发现,要想有多态,就必须要继承,继承是多态的前提。

多态的前提:

要有继承关系

要有方法的重写

其实没有重写也是可以的,但是不重写就没有意义

动物都有吃这个方法,但是每个具体的动物吃的实现不一样,变现出不同动物的特有属性

要有父类的引用指向子类的对象

父类名 f = new 子类名(...);

多态访问成员的特点:

1、成员变量

编译看左,运行看左

2、构造方法

创建子类对象的时候,先访问父类中的构造方法,对父类的数据先进行初始化

3、成员方法

编译看左,运行看右。

因为成员方法存在重写,所以访问看右边

4、静态成员方法

编译看左,运行也看左。

由于被static修饰的成员都是与类相关的,这里不是重写,所以运行的时候,访问的还是左边的。

class Fu3{int num=100;public void show(){System.out.println("这是父类中的show()f方法");}public static void fun(){System.out.println("这是父类中的静态fun()方法");}
}
class Zi3 extends Fu3{int num=1000;@Overridepublic void show() {System.out.println("这是子类中的show()方法");}public void show2() {System.out.println("这是子类中的特有方法");}public static void fun() {System.out.println("这是子类中的静态fun()方法");}}
public class PolymorphicDemo {public static void main(String[] args) {Fu3 fu3=new Zi3();System.out.println(fu3.num);fu3.show();// 这是子类中的show()方法fu3.fun();//这是父类里的静态方法}
}

class Father{public void show(){System.out.println("这是父类的show方法");}
}
class Son extends Father{@Overridepublic void show() {System.out.println("这是子类里的show方法");}public void show2() {System.out.println("这是子类里特有的show方法");}}
public class PolymorphicDemo2 {public static void main(String[] args) {Father father=new Son();father.show();//需求:我现在就想调用父类中的show方法,怎么办?}
}

多态的弊端:

多态无法访问父类中的方法名一样的方法

1、我就想使用父类中的方法,能不能用,能。不使用多态

2、如果我想使用子类中的特有方法,还必须使用多态,咋办?

1)就不使用多态,创建子类对象然后调用方法

但是在我上一个例子上,再次创建对象,还会在堆内存中开辟空间,很有可能会造成资源浪费

2、将子类看成一个小的类型,将父类看成一个大的类型,现在想要用小的类型中的方法

我们应该要将大的类型转成小的类型。在我们之前的做法是用强制类型转换。

如果在继承关系,也有类似的这样的做法就好了。

java替我们考虑到这样的问题,提供了一个技术给我们使用:向下转型

将父类的引用强制转换成子类的引用

子类类名 变量名 = (子类类名)父类的引用;

对象之间转型的问题:

1、向上转型:

Fu f = new Son();

2、向下转型

Son s = (Son)f;

int a = 10;

byte b = (byte)a;

向下转型需要注意的一个问题:

要求转型的类与父类引用存在继承关系,并且一开始创建多态的时候,使用的是该类。

关键字abstract,它可以修饰类,方法

1、抽象类中可以没有抽象方法,但是有抽象方法的类一定是抽象类

2、抽象类不能被实例化

3、要想实例化抽象类,必须用一个具体的子类继承它

注意:具体的子类继承抽象类,必须重写该抽象类中的所有的抽象方法

4、最终以抽象多态的形式进行实例化。

class Father2{public void show(){System.out.println("这是父类中的show方法");}
}
class Son2 extends Father2{@Overridepublic void show() {System.out.println("这是子类中的show方法");}public void show2() {System.out.println("这是子类中的特殊show方法");}}
public class PolymorphicDemo3 {public static void main(String[] args) {Father2 father=new Son2();//father.show2();//这里不能直接调用show2()因为父类里没有show2()无法编译Son2 s=(Son2) father;s.show2();s.show();}}

实例:

动物之猫和狗

class Animal2{public void eat(){System.out.println("吃");}
}
class Dog extends Animal2{@Overridepublic void eat() {System.out.println("狗吃肉");}public void lookDoor(){System.out.println("看门");}
}
class Cat extends Animal2{@Overridepublic void eat() {System.out.println("猫吃鱼");}public void catchMouse(){System.out.println("猫捉老鼠");}
}public class PolymorphicDemo4 {public static void main(String[] args) {Animal2 animal2=new Dog();animal2.eat();Dog d=(Dog) animal2;d.eat();d.lookDoor();Animal2 animal21=new Cat();animal21.eat();Cat c=(Cat) animal21;animal21.eat();((Cat) animal21).catchMouse();}
}

不同地方饮食文化不同的案例

Person

eat()

SouthPerson

eat()

NorthPerson

eat()

class Person {public void eat() {System.out.println("吃");}
}class SouthPerson extends Person {@Overridepublic void eat() {System.out.println("南方人吃米饭");}public void playMaJiang() {System.out.println("南方人打麻将");}
}class NorthPerson extends Person {@Overridepublic void eat() {System.out.println("北方人吃面食");}public void bath() {System.out.println("北方人搓澡");}
}public class PolymorphicDemo5 {public static void main(String[] args) {Person person = new SouthPerson();person.eat();SouthPerson s = (SouthPerson) person;s.eat();s.playMaJiang();Person person1 = new NorthPerson();person1.eat();NorthPerson n = (NorthPerson) person1;n.bath();n.eat();}
}

多态的好处有哪些?

1、多态可以使代码的扩展性很好(这是由继承所保证的)

2、多态可以使代码的维护性很好(这是由多态保证的)

class Animal {String name;int age;Animal() {}public Animal(String name, int age) {this.name = name;this.age = age;}public void sleep() {System.out.println("睡觉");}public void eat() {System.out.println("吃");}
}class Dog1 extends Animal {public Dog1() {}public Dog1(String name, int age) {this.name = name;this.age = age;}@Overridepublic void eat() {System.out.println("狗吃肉");}@Overridepublic void sleep() {System.out.println("狗卷着睡");}
}class Cat1 extends Animal {public Cat1() {}public Cat1(String name, int age) {this.name = name;this.age = age;}@Overridepublic void eat() {System.out.println("猫吃鱼");}@Overridepublic void sleep() {System.out.println("猫趴着睡");}}class AnimalTool {//工具类private AnimalTool() {}public static void useDog(Dog1 dog1) {dog1.sleep();dog1.eat();}public static void useCat(Cat1 cat1) {cat1.sleep();cat1.eat();}public static void useAnimal(Animal animal) {animal.eat();animal.sleep();}
}public class CatDogDemo {public static void main(String[] args) {System.out.println("=====第二种通过下面创建方法调用=====");//第一种方法调用子类Dog1 dog1 = new Dog1("小白哦", 2);dog1.eat();dog1.sleep();Cat1 cat1 = new Cat1("小号", 3);cat1.eat();cat1.sleep();System.out.println("=====第二种通过下面创建方法调用=====");//第二种通过下面创建方法调用Dog1 d1 = new Dog1("小白", 2);useDog(d1);Cat1 c1 = new Cat1("小红", 2);useCat(c1);System.out.println("====第三种通过工具类调用=====");//第三种通过工具类调用Dog1 d2 = new Dog1("小白", 2);AnimalTool.useDog(d2);Cat1 c2 = new Cat1("小红", 2);AnimalTool.useCat(c2);//这里注意工具类是私有的不可直接调用use方法//工具类里的内容是私有的不好改动System.out.println("=====用多态改进=====");Animal a1 = new Dog1("小白",2);AnimalTool.useAnimal(a1);Animal a2 = new Cat1("小红",2);AnimalTool.useAnimal(a2);}public static void useDog(Dog1 dog1) {//创建方法调用dog1.sleep();dog1.eat();}public static void useCat(Cat1 cat1) {cat1.sleep();cat1.eat();}
}

抽象的表述:

之前所说的猫,狗,猪,熊猫,老虎等等都是动物具体的例子,而动物本身是一个抽象的概念 但是回想一下我们之前都是将动物写成了一个具体的,而类又可以创建对象,但是实际上抽象的东西本身应该不能被实例化.

并且动物中吃的方法应该也不是一个具体的实现,以及所有动物共同拥有的方法在动物中应该都是抽象的表现

今天之后,把一个不具体的功能,叫做抽象方法,而如果一个类中有抽象方法,我们就把这个类称之为抽象类。

抽象类的特点:

1、抽象类和抽象方法都要用一个关键字修饰:abstract

修饰一个类 放在class的前面

举例: abstract class Animal3{}

修饰一个方法 一般是放在权限修饰符后面

定义一个抽象的show方法

举例:public abstract void show();

2、有抽象方法的类一定要是抽象类,抽象类不一定要有抽象方法,具体的类中不能有抽象方法,抽象类中既可以存在抽象方法

也可以存在有方法体的方法。

3、抽象类不能被实例化

既然不能被实例化,那写在抽象类中的方法如何被调用呢?

抽象类如何创建呢?

通过多态的形式,使用具体的子类去实例化调用方法,专业术语称之为:抽象多态

4、如果继承抽象类的是一个具体的子类,需要重写该抽象类中所有的抽象方法

如果继承抽象的也是一个抽象类,可以不去重写父类中的抽象方法,也可以选择性的去重写。

abstract class Animal3 {//注意://抽象方法没有方法体{},连大括号都没有,直接以分号结尾//java: 抽象方法不能有主体public abstract void eat();public abstract void drink();
}class Dog3 extends Animal3 {@Overridepublic void eat() {System.out.println("狗吃肉");}@Overridepublic void drink() {System.out.println("狗喝水");}
}abstract class Demo2 {public abstract void fun();public abstract void fun2();
}abstract class Demo3 extends Demo2 {@Overridepublic void fun() {System.out.println("抽象类Demo3中重写了fun方法");}@Overridepublic void fun2() {System.out.println("抽象类Demo3中重写了fun2方法");}
}public class AbstractDemo1 {public static void main(String[] args) {
//        Demo2 demo2=new Demo2();   //java: com.shujia.wyh.day11.Demo2是抽象的; 无法实例化//利用具体子类多态形式创建对象//抽象多态的形式Animal3 animal3 = new Dog3();animal3.drink();animal3.eat();//Demo2 demo2= new Demo2() //都是抽象无法调用}
}

抽象类的成员的特点:

成员变量:

既可以是变量,也可以是常量

构造方法:

可以存在构造方法,上一个程序中总结出抽象类不能被实例化,这里构造方法意义是什么?

之前在继承中要想初始化子类,必须先初始化父类,所以这里构造方法是提供初始化父类的作用

成员方法:

可以是抽象方法,但是具体的子类必须要重写该方法

也可以不是抽象方法,提高代码的复用性。

abstract class Animal4 {int a = 100;final int b = 20;Animal4() {System.out.println("这是Animal4中无参构造方法");//即使不去定义也会存在}public abstract void eat();public void show() {System.out.println("父类中不是抽象方法的show");}
}
class Cat4 extends Animal4{@Overridepublic void eat() {System.out.println("猫吃鱼");}
}
public class AbstractDemo2 {public static void main(String[] args) {Animal4 a = new Cat4();System.out.println(a.a);System.out.println(a.b);a.eat();a.show();}
}

不写抽象方法,也是可以的。

1、抽象类中可以没有抽象方法

2、抽象类不能被实例

抽象类中可以存在哪些关键字?

abstract关键字不能和哪些关键字共存?

private

static

final

abstract class YeTi{
//    YeTi(){
//        super();
//    }//不会报错因为所有的类都有一个共同的父类:object
//abstract可以和public关键字共存
public abstract void show();//private和abstract关键字冲突
//private abstract void show2(); java: 非法的修饰符组合: abstract和private//static和abstract关键字冲突
//    static abstract void show3();  // java: 非法的修饰符组合: abstract和static//final和abstract关键字冲突
//    final abstract void show4();  // java: 非法的修饰符组合: abstract和final}
public class AbstractDemo3 {public static void main(String[] args) {}
}

抽象类改进猫狗案例

abstract class Animal5{public abstract void eat();public abstract void sleep();}
class Dog5 extends Animal5 {@Overridepublic void eat() {System.out.println("狗吃肉");}@Overridepublic void sleep() {System.out.println("狗圈着睡");}public void play(){System.out.println("狗和狗玩");}
}
class Cat5 extends Animal5{@Overridepublic void eat() {System.out.println("猫吃鱼");}@Overridepublic void sleep() {System.out.println("猫趴着睡");}public void play(){System.out.println("猫和猫玩");}
}
public class AbstractTest1 {public static void main(String[] args) {Animal5 animal5=new Dog5();animal5.eat();animal5.sleep();Dog5 dog5=(Dog5) animal5;dog5.play();Animal5 animal51=new Cat5();animal51.sleep();animal51.eat();Cat5 cat5=(Cat5) animal51;cat5.play();}
}

假如我们在开发一个系统时需要对员工类进行设计,员工包含3个属性:姓名、工号以及工资。

经理也是员工,除了含有员工的属性外,另为还有一个奖金属性。

请使用继承的思想设计出员工类和经理类。要求类中提供必要的方法进行属性访问。

分析:

普通员工:

成员变量:姓名,工号,工资

成员方法:工作(敲代码)

经理

成员变量:姓名,工号,工资,奖金

成员方法:工作(做PPT)

abstract class Stuff{private String name;private String id;private int salary;public  Stuff(){}public Stuff(String name,String id,int salary){this.id=id;this.name=name;this.salary=salary;}public void setName(String name) {this.name = name;}public void setId(String id) {this.id = id;}public void setSalary(int salary) {this.salary = salary;}public String getName() {return name;}public String getId() {return id;}public int getSalary() {return salary;}public abstract void work();
}
class CommonStaff extends Stuff{public CommonStaff(){}public CommonStaff(String name, String id, int salary) {super(name, id, salary);}@Overridepublic void work() {System.out.println("敲代码");}
}
class Manager extends Stuff{//特有的属性 奖金private int bonus;public Manager(int bonus) {this.bonus = bonus;}public Manager(String name, String id, int salary, int bonus) {super(name, id, salary);this.bonus = bonus;}@Overridepublic void work() {System.out.println("做PPT");}
}public class AbstractTest4 {public static void main(String[] args) {//创建第一个对象Stuff s1 = new CommonStaff("小虎","KZ0080",100000);s1.work();//创建第二个对象Stuff s2 = new Manager("小明","SJ00030",200000,1000000);s2.work();}
}

更多推荐

第十天多态继承补充和final

本文发布于:2024-02-13 20:46:51,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1760418.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:第十天   多态   final

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!