1. 多态(polymorphism)
1. 1方法的多态性,
重载和覆写;
- 重载(overloading):1.方法名相同 2.参数类型和个数至少一个不同 3.返回类型和修饰符可以不同
- 覆盖(overriding):子类有一个方法,与父类某方法的名称、返回类型、参数相同,则称子类方法覆盖父类方法;注:子类方法不能缩小父类方法的访问权限
1.2 对象的多态性:
父子类对象的转换,分为两种:
- 父类 父类引用 = 子类实例, 自动;
- 子类 子类引用 = 父类实例, 强制;
2是强制转化,所以2的发生先有1,举个例子。
1.3 demo
demo1 父类 父类引用 = 子类实例, 自动
public class Parent {
public void method() {
System.out.println("Parent");
}
}
public class Subclass extends Parent{ //inherit from A
public void method() { //overrride
System.out.println("Subclass");
}
}
public class Main {
public static void main(String[] args) {
Parent p = new Subclass();
p.method();
}
}
运行结果
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191012143035790.png
demo2 子类 子类引用= 父类对象 强制
public class Main2 {
public static void main(String[] args) {
Parent p = new Subclass();
Subclass s = (Subclass) p;
s.method();
}
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191012143716128.png
但是如果没有1的 父类引用 = 子类对象,而直接强制转换子类引用 = 父类对象则会报错。
public class Main3 {
public static void main(String[] args) {
Parent p = new Parent();
Subclass s = p;
s.method();
}
}
表象:
父类的引用指向子类的对象。
成员变量: 编译看左边,运行看左边
编译看左边的意思就是父类有的方法和属性才能去调用
成员方法: 编译看左边,运行看右边
编译看左边的意思就是父类有的方法和属性才能去调用, 但运行的时候是运行的子类的成员方法。
构造方法:先初始化父类,在初始化子类
静态方法:编译看左边,运行看左边
1.4 总结
一般来说多态存在的前提:
- 要有继承(inherice)
- 要有重写(overriding)
- 父类引用指向子类对象
其实,方法(method)的覆写(Overriding)和重载(overloading)是java多态性的不同表现。overriding是Superclas和subclass之间的polymorphism。overloading是一个class中polymorphism的一种表现。
1.5 instanceof key word
Insatance instanceof class ——> boolen类型
public class Main4 {
public static void main(String args[]) {
Parent p = new Subclass();
System.out.println( p instanceof Parent);
System.out.println( p instanceof Subclass);
}
}
Result
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191012145641373.png
2. 抽象类(abstract class)
一个类去继承一个已经实现好的类的情况一般不可能出现,只能继承抽象类或实现接口。
2.1 抽象类
abstract class: 只声明,没实现。并用abstract关键字。
java类:普通类,抽象类:继承
接口:实现
单继承,多实现(只能继承一个父类)
抽象类:
- 和普通类很相似,也是要抽取共性
- 他和普通的类的差别在于抽象类里面可以定义抽象方法
抽象方法: 访问修饰符 abstract 返回类型 方法名字(参数类型 参数名);
普通方法:访问修饰符 返回类型 方法名字(参数类型 参数名){
具体实现代码
} - 抽象方法必须在抽象类里面
- 子类必须重写这个抽象类里面的抽象方法
一流的厂商出接口 - 抽象类和抽象方法必须有关键字abstract
- 抽象类不能被实例化,抽象类的定义就是 为了被继承
- 抽象类里面有构造方法,子类实例化的时候,先初始化父类,在初始化子类。
- 抽象类里面可以有普通方法,抽象类里面可以不定义抽象方法
- 抽象类里面可以定义普通方法,也可以没有普通方法,但有抽象方法的类必须是抽象类
2.2 demo
// superclass
public abstract class People {
String name;
public abstract void eat();//no method body
}
//subclass
public class Student extends People{
@Override
public void eat() {//override abstract class
System.out.println("Student eats in the school canteen");
}
}
//main()
public class Main {
public static void main(String args[]) {
People p = new Student();
p.eat();
}
}
Result
2.3 抽象类的应用–模板设计模式
这个其实我也不懂,在P209页java核心技术精讲里有个例子。
这里举个相似的例子。
3种类型,student,teacher,worker
student: eat , work , sleep
teacher: eat, work, sleep
work: :eat, work,sleep
设计一个程序,实现三个的功能,并使得不同的类型进行其各自的eat,sleep等功能。
//abstract class
public abstract class People {
String name;
public abstract void eat();
public abstract void work();
public abstract void study();
public abstract void sleep();
//subclass
public class Student extends People{
@Override
public void eat() {
System.out.println("Student eats in the school canteen");
}
@Override
public void work() {
}
@Override
public void study() {
System.out.println("Student studys at school");
}
@Override
public void sleep() {
System.out.println("Student sleeps in the dormitory");
}
}
//subclass
ublic class Teacher extends People{
@Override
public void eat() {
System.out.println("Teacher eats at home");
}
@Override
public void work() {
System.out.println("Teacher teaches studens at school");
}
@Override
public void study() {
// TODO Auto-generated method stub
}
@Override
public void sleep() {
System.out.println("Teacher sleeps at home");
}
}
//subclass
public class Worker extends People{
@Override
public void eat() {
System.out.println("worker eats on the site");
}
@Override
public void work() {
System.out.println("worker works on the site");
}
@Override
public void study() {
// TODO Auto-generated method stub
}
@Override
public void sleep() {
System.out.println("worker sleeps on the site");
}
}
//main
public class Main {
public static void main(String[] args) {
Student stu = new Student();
Action(stu);
System.out.println("*********************");
People tea = new Teacher();
Action(tea);
System.out.println("*********************");
People wor = new Worker();
Action(wor);
}
public static void Action(People p) {
p.eat();
p.work();
p.study();
p.sleep();
}
}
Result
继续扩展实现其他职业,只需要添加相应class, override相应的abstract method就可以,而不需要很多的代码量。抽象类起到了定义模板的功能。
2.4 abstract不能和那些关键字一起出现:
private:private不能被继承
static:抽象方法一旦被静态所修饰,可以通过类名.方法名来访问
Final: 被final修饰的属性是常量被修改,方法不被重写,类不被继承
3 接口 (interface)
3.1 interface
当一个类定义时全部由抽象方法和全局常量组成,那么这种类就称为接口(interface)。
3.2 特点 characteristic
图来自于 b站视频
3.3 demo
3.3.1 demo1 单继承,多实现
class subclass [extends superclass] [implements interface 1 , interface 2 , interface3…]
即就是:单继承,多实现,先继承,后实现。
Subclass
//interfaceA
public interface InterfaceA {
public static final String name ="InterfaceA";
public abstract void print();
}
//interfaceB
public interface InterfaceB {
public abstract void get();
}
//superclass
public class Superclass {
Superclass(){
System.out.println("Superclass");
}
}
//subclass
public class Subclass extends Superclass implements InterfaceA,InterfaceB {
@Override
public void get() {
System.out.println("InterfaceB get()");
}
@Override
public void print() {
System.out.println("print()");
}
}
//main()
public class Main {
public static void main(String[] args) {
Subclass s = new Subclass();
s.get();
InterfaceA ia = new Subclass();
ia.print();
}
}
Result
因为interface中只有abstract method和全局常量,所以可以简写。
完整定义
interface A{
public static final String name = "hello";
public abstract void print();
}
简化定义
interface A{
public String name = "hello";
public void print();
}
3.3.2 demo2 接口实现多继承
//interface
public interface A {
public String name = "ZhangSan";
public void printA();
}
//interface B
public interface B {
public void printB();
}
//interface C extends A, B
public interface C extends A, B{
public void printC();
}
//subclass implements A,B,C
public class Subclass implements A,B,C{
@Override
public void printC() {
System.out.println(C.name);
}
@Override
public void printB() {
System.out.println("print B");
}
@Override
public void printA() {
System.out.println("print A");
}
}
//main()
public class Main {
public static void main(String args[]) {
A a = new Subclass();
a.printA();
B b = new Subclass();
b.printB();
C c = new Subclass();
c.printC();
}
}
Result
3.3.3 demo3 使用接口定义标准
比如USB接口,具体的金士顿(Kingston)和闪迪(Sandisk)等,其中最很重要是读写功能。
//USB interface
public interface USB {
public void read();
public void write();
}
// Kingston implements USB
public class Kingston implements USB{
@Override
public void read() {
System.out.println("Kingston reads the doc line by line ");
}
@Override
public void write() {
System.out.println("Kinston writes the doc line by line");
}
}
//Sandisk implements USB
public class Sandisk implements USB{
@Override
public void read() {
System.out.println("Sandisk reads the doc byte by byte");
}
@Override
public void write() {
System.out.println("Sandisk writes the doc byte by byte");
}
}
//Computer
public class Computer {
public void plugin(USB b) {
b.read();
b.write();
}
}
//main()
public class Main {
public static void main(String[] args) {
Computer pc = new Computer();
USB kingston = new Kingston();
pc.plugin(kingston);
Sandisk sandisk = new Sandisk();
pc.plugin(sandisk);
}
}
Result
不管多少种USB设备,只要实现了USB interface都可以在computer上使用,所以interface就相当于制订了一个操作标准。
demo4和demo5来自java核心技术精讲
3.4 interface的实际作用 – 工厂设计模式(Factory)
demo3.5 interface的世纪作用—代理设计模式(proxy)
4. conclusion
普通类,抽象类和接口的区别