面向对象
多态
多态的概述及其代码体现
多态概述
-
某一个事物,在不同时刻表现出来的不同状态
-
举例:
Cat c=new Cat();
Animal a=new Cat();
猫可以是猫的类型。猫 m=new 猫();
同时猫也是动物的一种,也可以把猫称为动物。动物 d=new 猫();
多态前提
-
要有继承关系
-
要有方法重写。其实也可以没有,但是如果没有这个就没有意义
-
要有父类引用指向子类对象
父 f=new 子();
多态中的成员访问特点
多态中的成员特点
-
成员变量
编译看左边,运行看左边
-
构造方法
创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化
-
成员方法
编译看左边,运行看右边
-
静态方法
编译看左边,运行看左边
(静态和类相关,算不上重写,所以访问还是左边)
public class MyTest {
public static void main(String[] args) {
//多态的形式,来看一下成员变量的特点
//多态的形式来访问成员变量,编译看左边,运行也看左边。多态的形式访问成员变量,访问的都是父类的变量。
Fu fu = new Zi();
int n=fu.num;
System.out.println(n); //10
//多态的形式,来访问成员方法的特点
//编译看左边,运行看右边,编译期,看父类中有没有这个方法,如果有语法就报错,实际调用时,会以子类重写过后的为准。
//当然,子类确实没有重写,那就以父类方法为准。
fu.show();
fu.jing();
Fu.jing();
Zi.jing();
Zi zi = new Zi();
}
}
class Fu{
public Fu() {
System.out.println("父类 构造调用了");
}
int num=100;
public void show(){
System.out.println("fu show");
}
public static void jing(){
System.out.println("fu jing");
}
}
class Zi extends Fu{
int num=10;
public Zi() {
System.out.println("子类构造执行了");
}
@Override
public void show() {
System.out.println("zi show");
}
public static void jing() {
System.out.println("zi jing");
}
}
多态的好处
多态的好处
- 提高了代码的维护性(继承保证)
- 提高了代码的拓展性(由多态保证)
//我们现在设计的这个类,不好,扩展性不好,每增加一种动物,你就要增加一个重载的方法。
public class TestUtils {
private TestUtils() {
}
//方法形参的设计,用成父类型,那么就可以接收他所有的子类型。能够提高代码的扩展性。
public static void testEat(Animal an) {
//父类引用指向子类对象,
//多态形式调用成员方法,编译看左边,运行看右边
// Animal an=cat
//Animal an=dog
//Animal an=tiger
//Animal an=rabbit
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();
}*/
}
多态的弊端以及多态中向上转型和向下转型
多态的弊端
- 不能使用子类特有功能
public class MyTest {
public static void main(String[] args) {
//多态的弊端:不能调用子类特有的功能
Fu fu = new Zi(); //向上转型:多态就是向上转型。
fu.show();
//多态,不能直接调用,子类特有的功能。
//fu.hehe(); 报错。
/* Zi zi = new Zi();
zi.show();
zi.hehe();
*/
//我们可以采用向下转型,那调用子类特有的功能
System.out.println(fu.num); //200
Zi zi= (Zi) fu; //把父类引用,向下转型为子类型。
zi.hehe();
System.out.println(zi.num); //10
}
}
public class MyTest {
public static void main(String[] args) {
//09.05_ 案例演示 孔子装爹
/*
* 孔子爹,是一名Java讲师,非常有名,张三慕名前来,把孔子爹请到家里去讲课,此时就剩孔子一个人在家玩游戏。
* 这时候,李四也来孔子的家里,请孔子爹去他家里讲课,那这时孔子爹不在家,这个孔子不想失去这笔生意,他就乔装打扮一下,打扮成他爹的模样,去李四家里给李四讲课。实际他讲的是论语。讲完之后,孔子回到家,觉得假扮他爹太累了,所以卸下装扮,做回他自己,愉快的玩游戏去了。
*
* */
孔子爹 k爹= new 孔子();
System.out.println(k爹.age); //60;
k爹.teach();
//卸下装扮,做回我自己,向下转型。
孔子 kz= (孔子) k爹;
System.out.println(kz.age); //30
kz.playGame();
}
}
class 孔子爹{
int age=60;
public void teach(){
System.out.println("讲授Java");
}
}
class 孔子 extends 孔子爹{
int age=30;
@Override
public void teach() {
System.out.println("讲授论语");
}
public void playGame(){
System.out.println("玩游戏");
}
}
多态的内存图解
class Fu {
public void show() {
System.out.println("fu show");
}
}
class Zi extends Fu {
public void show() {
System.out.println("zi show");
}
public void method() {
System.out.println("zi method");
}
}
class DuoTaiTest3 {
public static void main(String[] args){
Fu f = new Zi();
f.method(); //报错 ,不能直接调用子类特有的方法
f.show();
}
}
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();// 你
}
}
抽象类
抽象类的概述及其特点
抽象类概述
- 在java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类
抽象类特点
-
抽象类和抽象方法方法必须用abstr关键字修饰
抽象类格式: abstract class 类名 { }
抽象方法格式: public abstract void eat();
-
抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
-
抽象类中可以有构造方法,抽象类不能进行实例化,那么要构造方法有什么用呢?
用于子类访问父类数据时的初始化
-
抽象类不能直接实例化,那么抽象类该如何实例化呢?
按照多态的方式,由具体的子类实例化,其实这也是多态的一种,抽象类多态
-
抽象类的子类
要么是抽象类
要么重写抽象类中的所有抽象方法
public class MyTest {
public static void main(String[] args) {
//Animal animal = new Animal();
Cat cat = new Cat();
Dog dog = new Dog();
}
}
//abstract 抽象的,可以修饰类,修饰方法。
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("狗晚上睡觉");
}
}
public class MyTest {
public static void main(String[] args) {
//抽象类的语法特点:
//1.抽象类中,可以没有抽象方法,也可以有抽象方法。
//2.一个类中,一旦有了抽象方法,此类就必须为抽象类。
//3.抽象类,不能直接实例化,但是我们可以采用多态的形式,来间接实例化。
//4.抽象类中所有抽象方法,强制子类必须重写
//5.抽象类的子类有中选择,选择1.重写抽象类中的所有抽象方法,选择2:你自己也是个抽象类
//6.可以没有抽象方法,也可以有抽象方法。这样设计的考虑,非抽象方法,可以让子类直接继承使用,对于抽象方法,是要求子类必须重写的。
}
}
abstract class A{
public void show(){
}
public abstract void b();
public abstract void c();
}
class B extends A {
@Override
public void b() {
}
@Override
public void c() {
}
}
abstract class C extends A {
public abstract void cc();
}
class D extends C{
@Override
public void b() {
}
@Override
public void c() {
}
@Override
public void cc() {
}
}
public class MyTest2 {
public static void main(String[] args) {
//抽象类,不能直接实例化,我们可以通过多态的形式,间接实例化父类
Fu fu= new Zi();
}
}
abstract class Fu{
int num=20;
final int A=200;
//抽象类有构造方法,作用:用于子类访问父类数据时的初始化
public Fu(){
System.out.println("父类的构造执行了");
}
}
class Zi extends Fu{
public Zi() {
System.out.println("子类的构造执行了");
}
}
抽象类的成员特点
抽象类的成员特点
-
成员变量:既可以是变量,也可以是常量(不被abstract修饰)
-
构造方法:有
用于子类访问父类数据的初始化
-
成员方法:既可以是抽象的,也可以是非抽象的
抽象类的成员方法特性
- 抽象方法 强制要求子类做的事情
- 非抽象方法 子类继承的事情,提高代码的复用性
public class MyTest {
public static void main(String[] args) {
/* A:
案例演示
假如我们在开发一个系统时需要对员工(Employee) 类进行设计,员工包含3个属性:姓名、工号以及工资(salary)。
经理(Manager) 也是员工,除了含有员工的属性外,另为还有一个奖金(bonus) 属性。
然后定义工作的方法.
请使用继承的思想设计出员工类和经理类。*/
Person p = new Manager();
p.name = "沈公子";
p.id = 10;
p.sal = 2000;
System.out.println(p.name);
System.out.println(p.id);
System.out.println(p.sal);
p.work();
Manager m = (Manager) p;
m.bonus = 6000;
m.businessTrip();
System.out.println(m.bonus);
System.out.println("==================");
p = new Employee();
//类型转换异常。
//java.lang.ClassCastException:org.westos.demo6.Manager cannot be cast to org.westos.demo6.Employee
Employee e = (Employee) p;
p.name = "王五";
p.id = 22;
p.sal = 1000;
System.out.println(p.name);
System.out.println(p.id);
System.out.println(p.sal);
p.work();
//一个类如果没有抽象方法,可不可以定义为抽象类 ? 如果可以,有什么意义 ?
//可以,这个类不想让外界创建对象。
//abstract不能和哪些关键字共存 ?
//private 矛盾 abstract 强制子类必须重写 private 私有的不能继承,重写不了
// final 矛盾 final方法子类不能重写 abstract 又强制重写
// static 方法不参与重写 abstract 他又要重写
}
}
abstract class A{
public abstract void hehe();
}
public abstract class Person {
//姓名、工号以及工资(salary)。
//工作的方法
public String name;
public int id;
public double sal;
public abstract void work();
}
public class Employee extends Person{
@Override
public void work() {
System.out.println("员工在一线进行生产工作");
}
}
public class Manager extends Person{
double bonus;
@Override
public void work() {
System.out.println("经理工作的内容是管理工作");
}
public void businessTrip(){
System.out.println("经理需要出差");
}
}
接口
接口的概述及其特点
接口概述
- 为了体现事物功能的拓展性,java中就提供了接口来定义这些额外功能,并不给出具体事件,只需要在要实现这些功能的对象这里额外实现功能即可
接口特点
-
接口用关键字interface表示 格式: interface 接口名 { }
-
类实现接口用implements表示 格式: class 类名 implements 接口名 { }
-
接口不能实例化
接口按照多态的方式来实例化
-
接口的子类
可以是抽象类,但是意义不大
可以是具体类,要重写接口中所有的抽象方法(推荐方案)
public class MyTest {
public static void main(String[] args) {
//接口:是为了定义一些额外扩展的功能,哪些事物,想要具备这些功能,可以对该接口进行实现。
//接口不能实例化。
/* Animal an = new TomCat();
an.sleep();
an.eat();
//父接口指向子类对象,这也是多态。
MyInterface myInterface= new TomCat();
myInterface.jump();*/
TomCat tomCat = new TomCat();
Animal an = tomCat;
an.sleep();
an.eat();
MyInterface myInterface = tomCat;
myInterface.jump();
System.out.println("=============================");
Dog dog = new Dog();
myInterface= dog;
myInterface.jump();
an=dog;
an.eat();
an.sleep();
}
}
// interface 定义一个接口
public interface MyInterface {
//在接口中,提供扩展的功能
public abstract void jump();
}
public abstract class Animal {
public abstract void eat();
public abstract void sleep();
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sleep() {
System.out.println("猫白天睡觉");
}
public void catchMouse() {
System.out.println("抓老鼠");
}
}
public class TomCat extends Animal implements MyInterface {
@Override
public void eat() {
System.out.println("汤姆猫爱吃小鱼干");
}
@Override
public void sleep() {
System.out.println("汤姆猫天天睡觉");
}
@Override
public void jump() {
System.out.println("汤姆猫,经过不断的练习学会了跳高");
}
}
public class Dog extends Animal implements MyInterface{
@Override
public void jump() {
System.out.println("狗经过不断学习,学会为了跳高");
}
@Override
public void eat() {
System.out.println("狗吃骨头");
}
@Override
public void sleep() {
System.out.println("狗累了就睡觉");
}
}
接口的成员特点
接口的成员特点
-
成员变量:只能是常量,并且是静态的
默认修饰符:public static final
建议:自己手动给出
-
构造方法:接口没有构造方法
-
成员方法:只能是抽象方法
默认修饰符:public abstract
建议:自己手动给出
public class MyTest {
public static void main(String[] args) {
//接口的子类有两种选择:1.重写接口中的所有抽象方法,2.自己本身就是一个抽象类 但是意义不大。
//接口中的成员特点:
//1.接口中的成员变量,全部是公共的静态常量 前面存在默认修饰符 public static final
System.out.println(A.NUM); //接口名直接调用
//2.JDK1.7 之前接口中的方法,全部是抽象方法,不存在非抽象方法。方法的前面存在 默认修饰符 public abstract
//3.接口中没有构造方法这一说。
//4.接口不能直接new对象。
}
}
interface A{
public static final int NUM=100;
int N=20;
public abstract void a();
public abstract void aa();
int sum(int a,int b);
}
class B implements A{
@Override
public void a() {
}
@Override
public void aa() {
}
@Override
public int sum(int a, int b) {
return 0;
}
}
类与类、类与接口、接口与接口的关系
类与类、类与接口、接口与接口的关系
-
类与类
继承关系,只能单继承,可以多层继承
-
类与接口
实现关系,可以单实现,也可以多实现
并且还可以在继承一个类的同时实现多个接口
-
接口与接口
继承关系,可以单继承,也可以多继承
public class MyTest2 {
public static void main(String[] args) {
//类和类之间的关系: extends 继承关系 并且是单继承。
//类和接口之间的关系:implements 实现关系,并且可以多实现。
//接口和接口之间的关系:extends 继承关系 并且还是多继承。一个接口可以继承多个接口。
}
}
interface AA{
void aa();
}
interface BB{
void bb();
}
interface CC{
void cc();
}
interface DD extends AA,BB,CC{
void dd();
}
class MyDD implements DD{
@Override
public void aa() {
}
@Override
public void bb() {
}
@Override
public void cc() {
}
@Override
public void dd() {
}
}
//一个类 可以实现多个接口。这个类,要把他所有实现的接口中的所有抽象方法都要重写。
class MyClss implements AA,BB,CC{
@Override
public void aa() {
}
@Override
public void bb() {
}
@Override
public void cc() {
}
}
抽象类和接口的区别
成员区别
-
抽象类:
成员变量:可以是变量,也可以是常量
构造方法:有
成员方法:可以抽象,也可以非抽象
-
接口:
成员变量:只可以常量
成员方法:只可以抽象
关系区别
-
类与类
继承、单继承
-
类与接口
实现、单实现、多实现
-
接口与接口
继承、单继承、多继承
设计理念区别
- 抽象类 被继承体现的是:“is a”的关系。 抽象类中定义的是该继承体系的共性功能
- 接口 被实现体现的是:“lika a”的关系。 接口中定义的是该继承体系的拓展功能
public class MyTest {
public static void main(String[] args) {
//JDK1.8之后针对接口,做了一些新的定义。
//JDK1.8之后,他允许给出方法的具体实现,但是这个方法得用default来修饰。
//JDK1.8之后,接口中可以定义静态方法
//Java中的接口,更多的是来定义一些规则和规范的,以实现这个扩展性。
Zi zi = new Zi();
zi.aa();
zi.bb();
AA.test();
}
}
interface AA{
// void ccc();
public default void aa(){
System.out.println("aaa");
}
public static void test(){
System.out.println("abc");
}
}
interface BB {
default void bb(){
System.out.println("bbb");
}
}
class Fu1{
public void show(){
System.out.println("fu1 show");
}
}
class Fu2 {
public void show2() {
System.out.println("fu2 show");
}
}
class Zi implements AA,BB{
//抽象类和接口的区别
//抽象类中,可以定义抽象方法,也可以定义非抽象方法。
//接口:接口里面定义的是抽象方法,JDK1.8可以定义 default修饰的方法和静态方法。
//抽象类有构造方法的,接口没有构造方法这一说。
//抽象类可以定义成员变量也可以定义常量,接口中全是公共的静态常量。
//设计思想:抽象类,他是抽象所有子类的共性功能,并不给出共性功能的具体实现,而是交由子类根据自身的差异性,去做具体实现。
//接口:体现一种扩展的思想,通常用来定义一些规范和规则,哪些事物想要具备这些扩展功能,可以实现具体的接口。接口他只需要维护一套规范或者说规则,那么具体对规范的实现,是由子类来具体实现的。
}
完