您的位置:首页 > 其它

9. 面向对象 -- 多态、抽象、接口

2017-11-27 10:02 267 查看

1:final关键字(掌握)

       由于继承中方法有一个现象:方法重写。

       所以,父类的功能,就会被子类给覆盖调。

       有些时候,我们不想让子类去覆盖掉父类的功能,只能让他使用。

       这个时候,针对这种情况,Java就提供了一个关键字:final



class Fu {
public final void show() {
System.out.println("这里是绝密资源,任何人都不能修改");//结果显示
}
}
class Zi extends Fu {
//public void show() {   // Zi中的show()无法覆盖Fu中的show()
//System.out.println("这是一堆垃圾");
}
class ZiDemo {
public static void main(String[] args) {
Zi z = newZi();
z.show();
}
}

       (1)final:最终的意思。常见的是它可以修饰类,方法,变量。

       (2)特点:

              A:final可以修饰类,该类不能被继承。

              B:final可以修饰方法,该方法不能被重写。(覆盖,复写)

              C:final可以修饰变量,该变量不能被重新赋值。因为这个变量其实常量。

常量:A:字面值常量              "hello",10,true

          B:自定义常量              finalint x = 10;

       (3)面试题:

              A:final修饰局部变量的问题

                     a:基本类型:基本类型的值不能发生改变。

                     b:引用类型:引用类型的地址值不能发生改变,但是对象的内容是可以改变的



class Student {
int age = 10;
}
class FinalTest {
public static void main(String[] args) {
//局部变量是基本数据类型
int x =10;
x = 100;
System.out.println(x);          //100
final int y = 10;
//无法为最终变量y分配值
//y = 100;
System.out.println(y);          //10
System.out.println("--------------");
//局部变量是引用数据类型
Student s = newStudent();
System.out.println(s.age);       //10
s.age = 100;
System.out.println(s.age);       //100
System.out.println("--------------");
final Student ss = new Student();
System.out.println(ss.age);      //10
ss.age = 100;
System.out.println(ss.age);      //100
//重新分配内存空间(地址值)
//无法为最终变量ss分配值
//ss = new Student();
}
}

              B:final修饰变量的初始化时机

                     a:被final修饰的变量只能赋值一次。

b:在构造方法完毕前。(非静态的常量)

                     c:常见的给值

                            定义的时候。(推荐)

                            构造方法中。

 

classDemo {
//intnum = 10;
//finalint num2 = 20;
intnum;
finalint num2;
{
//num2= 10;
}
publicDemo() {
num= 100;
//无法为最终变量num2分配值
//num2= 200;
}
}
class FinalTest2 {
publicstatic void main(String[] args) {
Demod = new Demo();
System.out.println(d.num);
System.out.println(d.num2);
}
}

2:多态(掌握)

       (1)多态:同一个对象(事物),在不同时刻体现出来的不同状态。

       (2)多态的前提:

              A:要有继承关系。

              B:要有方法重写。

                     其实没有也是可以的,但是如果没有这个就没有意义。

                            动物 d = new 猫();

                            d.show();

                            动物 d = new 狗();

                            d.show();

              C:要有父类引用指向子类对象。

                     父 f = new 子();       

       (3)多态的分类:

              a:具体类多态

                     class Fu {}

                     class Zi extends Fu {}

                     Fu f = new Zi();

              b:抽象类多态

                     abstract class Fu {}

                     class Zi extends Fu {}

                     Fu f = new Zi();

              c:接口多态

                     interface Fu {}

                     class Zi implements Fu {}

                     Fu f = new Zi();

(4)多态中的成员访问特点

              A:成员变量          编译看左边,运行看左边

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

              C:成员方法          编译看左边,运行看右边(由于成员方法存在方法重写,所以它运行看右边)

              D:静态方法          编译看左边,运行看左边(静态和类相关,算不上重写,所以,访问还是左边的)

class Fu {
publicint num = 100;
publicvoid show() {
System.out.println("showFu");
}
publicstatic void function() {
System.out.println("functionFu");
}
}
class Zi extends Fu {
publicint num = 1000;
publicint num2 = 200;
publicvoid show() {
System.out.println("showZi");
}
publicvoid method() {
System.out.println("methodzi");
}
publicstatic void function() {
System.out.println("functionZi");
}
}
class DuoTaiDemo {
publicstatic void main(String[] args) {
//要有父类引用指向子类对象。
//父 f = new 子();
Fuf = new Zi();
System.out.println(f.num);      //100  成员变量      编译看左边,运行看左边
//System.out.println(f.num2);   //找不到符号
f.show();                               //show Zi  成员方法      编译看左边,运行看右边
//f.method();                          //找不到符号
f.function();                           //function Fu  成员方法编  译看左边,运行看右边
}
}

(5)多态的好处:

              A:提高代码的维护性(继承体现)

              B:提高代码的扩展性(多态体现)

       (6)多态的弊端:

              父不能使用子的特有功能。

              现象:子可以当作父使用,父不能当作子使用。

       (7)我就想使用子类的特有功能?行不行?

                     行。

              A:创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了)

              B:把父类的引用强制转换为子类的引用。(向下转型)

       对象间的转型问题:

              向上转型:

                     Fu f = new Zi();

              向下转型:

                     Zi z = (Zi)f; //要求该f必须是能够转换为Zi的。

class Fu {
publicvoid show() {
System.out.println("showfu");
}
}
class Zi extends Fu {
publicvoid show() {
System.out.println("showzi");
}
publicvoid method() {
System.out.println("methodzi");
}
}
class DuoTaiDemo4 {
publicstatic void main(String[] args) {
//测试
Fuf = new Zi();
f.show();
//f.method();                 //父类中没有method()方法
//创建子类对象
//Ziz = new Zi();
//z.show();
//z.method();
//你能够把子的对象赋值给父亲,那么我能不能把父的引用赋值给子的引用呢?
//如果可以,但是如下
Zi z =(Zi)f;                  //(可以,但是很多时候不合理。向下转型,太占内存了)
z.show();
z.method();
}
}

       (8)ClassCastException类型转换异常:一般在多态的向下转型中容易出现

class Animal {
publicvoid eat(){}
}
class Dog extends Animal {
publicvoid eat() {}
publicvoid lookDoor() {

}
}
class Cat extends Animal {
publicvoid eat() {
}
publicvoid playGame() {
}
}

class DuoTaiDemo5 {
publicstatic void main(String[] args) {
//内存中的是狗
Animala = new Dog();
Dogd = (Dog)a;
//内存中是猫
a= new Cat();
Catc = (Cat)a;       //向下转型
//内存中是猫
Dogdd = (Dog)a; //再次向下转型发生ClassCastException类型转换异常
}
}

       (9)多态的练习

              A:猫狗案例

              B:老师和学生案例

C:看程序写结果:先判断有没有问题,如果没有,写出结果

多态的成员访问特点:

              方法:编译看左边,运行看右边。

继承的时候:

              子类中有和父类中一样的方法,叫重写。

              子类中没有父亲中出现过的方法,方法就被继承过来了。

class A {
publicvoid show() {
show2();
}
publicvoid show2() {
System.out.println("我");
}
}
class B extends A {
publicvoid show2() {
System.out.println("爱");
}
}
class C extends B {
publicvoid show() {
super.show();
}
publicvoid show2() {
System.out.println("你");
}
}
public class DuoTaiTest4 {
publicstatic void main(String[] args) {
Aa = new B();
a.show();                             //爱
Bb = new C();
b.show();                             //你
}
}

3:抽象类(掌握)

       (1) 一个没有具体的方法体的方法是抽象的方法。在一个类中如果有抽象方法,该类必须定义为抽象类。

       (2)抽象类的特点

              A:抽象类和抽象方法必须用关键字abstract修饰

              B:抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类

              C:抽象类不能实例化

因为它不是具体的。

                     抽象类有构造方法,但是不能实例化?构造方法的作用是什么呢?

                     用于子类访问父类数据的初始化

              D:抽象类的子类

                     a:如果不想重写抽象方法,该子类是一个抽象类。

                     b:重写所有的抽象方法,这个时候子类是一个具体的类。

抽象类的实例化其实是靠具体的子类实现的。是多态的方式。

                     Animal a =new Cat();

//abstract class Animal //抽象类的声明格式
abstract class Animal {
//抽象方法
//publicabstract void eat(){} //空方法体,这个会报错。抽象方法不能有主体
publicabstract void eat();
publicAnimal(){}
}
//子类是抽象类
abstract class Dog extends Animal{}

//子类是具体类,重写抽象方法
class Cat extends Animal {
publicvoid eat() {
System.out.println("猫吃鱼");
}
}
class AbstractDemo {
publicstatic void main(String[] args) {
//创建对象
//Animal是抽象的; 无法实例化
//Animala = new Animal();
//通过多态的方式
Animala = new Cat();
a.eat();
}
}

       (3)抽象类的成员特点:

              成员变量:既可以是变量,也可以是常量。

              构造方法:有。用于子类访问父类数据的初始化。

              成员方法:既可以是抽象的,也可以是非抽象的。

       抽象类的成员方法特性:

              A:抽象方法         强制要求子类做的事情。

              B:非抽象方法      子类继承的事情,提高代码复用性。

abstract class Animal {
publicint num = 10;
publicfinal int num2 = 20;
publicAnimal() {}
publicAnimal(String name,int age){}
publicabstract void show();
publicvoid method() {
System.out.println("method");
}
}
class Dog extends Animal {
publicvoid show() {
System.out.println("showDog");
}
}
class AbstractDemo2 {
publicstatic void main(String[] args) {
//创建对象
Animala = new Dog();
a.num= 100;
System.out.println(a.num);
//a.num2= 200;
System.out.println(a.num2);
System.out.println("--------------");
a.show();
a.method();
}
}

(4)抽象类的练习

              A
e349
:猫狗案例练习

/*
猫狗案例
具体事物:猫,狗
共性:姓名,年龄,吃饭

分析:从具体到抽象
猫:
成员变量:姓名,年龄
构造方法:无参,带参
成员方法:吃饭(猫吃鱼)

狗:
成员变量:姓名,年龄
构造方法:无参,带参
成员方法:吃饭(狗吃肉)

因为有共性的内容,所以就提取了一个父类。动物。
但是又由于吃饭的内容不一样,所以吃饭的方法是抽象的,
而方法是抽象的类,类就必须定义为抽象类。

抽象动物类:
成员变量:姓名,年龄
构造方法:无参,带参
成员方法:吃饭();

实现:从抽象到具体
动物类:
成员变量:姓名,年龄
构造方法:无参,带参
成员方法:吃饭();

狗类:
继承自动物类
重写吃饭();

猫类:
继承自动物类
重写吃饭();
*/
//定义抽象的动物类
abstract class Animal {
//姓名
private String name;
//年龄
private int age;

public Animal() {}

public Animal(String name,int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

//定义一个抽象方法
public abstract void eat();
}

//定义具体的狗类
class Dog extends Animal {
public Dog() {}

public Dog(String name,int age) {
super(name,age);
}

public void eat() {
System.out.println("狗吃肉");
}
}

//定义具体的猫类
class Cat extends Animal {
public Cat() {}

public Cat(String name,int age) {
super(name,age);
}

public void eat() {
System.out.println("猫吃鱼");
}
}

//测试类
class AbstractTest {
public static void main(String[] args) {
//测试狗类
//具体类用法
//方式1:
Dog d = new Dog();
d.setName("旺财");
d.setAge(3);
System.out.println(d.getName()+"---"+d.getAge());
d.eat();
//方式2:
Dog d2 = new Dog("旺财",3);
System.out.println(d2.getName()+"---"+d2.getAge());
d2.eat();
System.out.println("---------------------------");

Animal a = new Dog();
a.setName("旺财");
a.setAge(3);
System.out.println(a.getName()+"---"+a.getAge());
a.eat();

Animal a2 = new Dog("旺财",3);
System.out.println(a2.getName()+"---"+a2.getAge());
a2.eat();

//练习:测试猫类(略)
}
}


              B:老师案例练习

/*
老师案例
具体事物:基础班老师,就业班老师
共性:姓名,年龄,讲课。

分析:
基础班老师
姓名,年龄
讲课。
就业班老师
姓名,年龄
讲课。
实现:
老师类
基础班老师
就业班老师
*/
//定义抽象的老师类
abstract class Teacher {
//姓名
private String name;
//年龄
private int age;

public Teacher() {}

public Teacher(String name,int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

//抽象方法
public abstract void teach();
}

//基础班老师类
class BasicTeacher extends Teacher {
public BasicTeacher(){}

public BasicTeacher(String name,int age) {
super(name,age);
}

public void teach() {
System.out.println("基础班老师讲解JavaSE");
}
}

//就业班老师类
class WorkTeacher extends Teacher {
public WorkTeacher(){}

public WorkTeacher(String name,int age) {
super(name,age);
}

public void teach() {
System.out.println("就业班老师讲解JavaEE");
}
}

class AbstractTest2 {
public static void main(String[] args) {
//具体的类测试,自己玩

//测试(多态)
//基础班老师
Teacher t = new BasicTeacher();
t.setName("刘意");
t.setAge(30);
System.out.println(t.getName()+"---"+t.getAge());
t.teach();
System.out.println("--------------");

t = new BasicTeacher("刘意",30);
System.out.println(t.getName()+"---"+t.getAge());
t.teach();
System.out.println("--------------");

//就业班老师
t = new WorkTeacher();
t.setName("林青霞");
t.setAge(27);
System.out.println(t.getName()+"---"+t.getAge());
t.teach();
System.out.println("--------------");

t = new WorkTeacher("林青霞",27);
System.out.println(t.getName()+"---"+t.getAge());
t.teach();
}
}


              C:学生案例练习

/*
学生案例
具体事务:基础班学员,就业班学员
共性:姓名,年龄,班级,学习,吃饭

分析:
基础班学员
成员变量:姓名,年龄,班级
成员方法:学习,吃饭
就业班学员
成员变量:姓名,年龄,班级
成员方法:学习,吃饭

得到一个学员类。
成员变量:姓名,年龄,班级
成员方法:学习,吃饭

实现:
学员类
基础班学员
就业班学员
*/
//定义抽象学员类
abstract class Student {
//姓名
private String name;
//年龄
private int age;
//班级
private String grand;

public Student() {}

public Student(String name,int age,String grand) {
this.name = name;
this.age = age;
this.grand = grand;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getGrand() {
return grand;
}

public void setGrand(String grand) {
this.grand = grand;
}

//学习
public abstract void study();

//吃饭
public void eat() {
System.out.println("学习累了,就该吃饭");
}
}

//具体基础班学员类
class BasicStudent extends Student {
public BasicStudent() {}

public BasicStudent(String name,int age,String grand) {
super(name,age,grand);
}

public void study() {
System.out.println("基础班学员学习的是JavaSE");
}
}

//具体就业班学员类
class WorkStudent extends Student {
public WorkStudent() {}

public WorkStudent(String name,int age,String grand) {
super(name,age,grand);
}

public void study() {
System.out.println("就业班学员学习的是JavaEE");
}
}

class AbstractTest3 {
public static void main(String[] args) {
//我仅仅测试基础班学员
//按照多态的方式测试
Student s = new BasicStudent();
s.setName("林青霞");
s.setAge(27);
s.setGrand("1111");
System.out.println(s.getName()+"---"+s.getAge()+"---"+s.getGrand());
s.study();
s.eat();
System.out.println("--------------");

s = new BasicStudent("武鑫",48,"1111");
System.out.println(s.getName()+"---"+s.getAge()+"---"+s.getGrand());
s.study();
s.eat();

//就业班测试留给自己玩
}
}


              D:员工案例练习

/*
假如我们在开发一个系统时需要对员工类进行设计,员工包含3个属性:姓名、工号以及工资。
经理也是员工,除了含有员工的属性外,另为还有一个奖金属性。
请使用继承的思想设计出员工类和经理类。要求类中提供必要的方法进行属性访问。

分析:
普通员工类
成员变量:姓名、工号以及工资。
成员方法:工作
经理类:
成员变量:姓名、工号以及工资,奖金属性
成员方法:工作

实现:
员工类:
普通员工类:
经理类:
*/
//定义员工类
abstract class Employee {
//姓名、工号以及工资
private String name;
private String id;
private int salary;

public Employee() {}

public Employee(String name,String id,int salary) {
this.name = name;
this.id = id;
this.salary = salary;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public int getSalary() {
return salary;
}

public void setSalary(int salary) {
this.salary = salary;
}

//工作
public abstract void work();
}

//普通员工类
class Programmer extends Employee {
public Programmer(){}

public Programmer(String name,String id,int salary) {
super(name,id,salary);
}

public void work() {
System.out.println("按照需求写代码");
}
}

//经理类
class Manager extends Employee {
//奖金
private int money; //bonus 奖金

public Manager(){}

public Manager(String name,String id,int salary,int money) {
super(name,id,salary);
this.money = money;
}

public void work() {
System.out.println("跟客户谈需求");
}

public int getMoney() {
return money;
}

public void setMoney(int money) {
this.money = money;
}
}

class AbstractTest4 {
public static void main(String[] args) {
//测试普通员工
Employee emp = new Programmer();
emp.setName("林青霞");
emp.setId("czbk001");
emp.setSalary(18000);
System.out.println(emp.getName()+"---"+emp.getId()+"---"+emp.getSalary());
emp.work();
System.out.println("-------------");
emp = new Programmer("林青霞","czbk001",18000);
System.out.println(emp.getName()+"---"+emp.getId()+"---"+emp.getSalary());
emp.work();
System.out.println("-------------");

/*
emp = new Manager();
emp.setName("刘意");
emp.setId("czbk002");
emp.setSalary(8000);
emp.setMoney(2000);
*/
//由于子类有特有的内容,所以我们用子类来测试
Manager m = new Manager();
m.setName("刘意");
m.setId("czbk002");
m.setSalary(8000);
m.setMoney(2000);
System.out.println(m.getName()+"---"+m.getId()+"---"+m.getSalary()+"---"+m.getMoney());
m.work();
System.out.println("-------------");

//通过构造方法赋值
m = new Manager("刘意","czbk002",8000,2000);
System.out.println(m.getName()+"---"+m.getId()+"---"+m.getSalary()+"---"+m.getMoney());
m.work();
}
}


       (5)抽象类的几个小问题

              A:抽象类有构造方法,不能实例化,那么构造方法有什么用?

                     用于子类访问父类数据的初始化

              B:一个类如果没有抽象方法,却定义为了抽象类,有什么用?

                     为了不让创建对象

              C:abstract不能和哪些关键字共存

                     a:     final        冲突

                     b:    private    冲突

                     c:     static      无意义

abstract class Fu {
//publicabstract void show();
//非法的修饰符组合: abstract和private
//privateabstract void show();
//非法的修饰符组合
//finalabstract void show();
//非法的修饰符组合
staticabstract void show();
publicstatic void method() {
System.out.println("method");
}
}
class Zi extends Fu {
publicvoid show() {}
}
class AbstractDemo3 {
publicstatic void main(String[] args) {
Fu.method();
}
}

4:接口(掌握)

       (1)回顾猫狗案例,它们仅仅提供一些基本功能。

          比如:猫钻火圈,狗跳高等功能,不是动物本身就具备的,

          是在后面的培养中训练出来的,这种额外的功能,java提供了接口表示。

       (2)接口的特点:

              A:接口用关键字interface修饰

                     interface 接口名 {}

              B:类实现接口用implements修饰

                     class 类名 implements 接口名{}

              C:接口不能实例化

那么,接口如何实例化呢?

                     按照多态的方式来实例化。

              D:接口的实现类

                     a:可以是抽象类。但是意义不大。

                     b:可以是具体类。要重写接口中的所有抽象方法。(推荐方案)

   由此可见:

          A:具体类多态(几乎没有)

          B:抽象类多态(常用)

          C:接口多态(最常用)

       (3)接口成员特点:

              成员变量;只能是常量,并且是静态的。

                            默认修饰符:public static final           建议:自己手动给出。

              构造方法:接口没有构造方法。

              成员方法:只能是抽象方法。

                            默认修饰符:public abstract               建议:自己手动给出。

       所有的类都默认继承自一个类:Object。

       类Object 是类层次结构的根类。每个类都使用 Object 作为超类。 

(4)类与类,类与接口,接口与接口

              A:类与类

                     继承关系,只能单继承,可以多层继承

              B:类与接口

                     实现关系,可以单实现,也可以多实现。

                     还可以在继承一个类的同时,实现多个接口

              C:接口与接口

                     继承关系,可以单继承,也可以多继承

       (5)抽象类和接口的区别

              A:成员区别

                     抽象类:

成员变量:可以变量,也可以常量

              构造方法:有

              成员方法:可以抽象,也可以非抽象

                     接口:

成员变量:只可以常量

              成员方法:只可以抽象

              B:关系区别:

                     类与类

                                   继承,单继承

                     类与接口

                                   实现,单实现,多实现

                     接口与接口

                                   继承,单继承,多继承:

              C:设计理念不同

                     抽象类:被继承体现的是:”is a”的关系。   抽象类中定义的是该继承体系的共性功能。

                     接口: 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: