【Java 09】面向对象(下) - abstract(抽象类和抽象方法)、模板方法模式、接口、代理模式、内部类

25 篇文章 0 订阅
20 篇文章 0 订阅

一 面向对象下二

1 抽象类和抽象方法(abstract)

随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。

类的设计应该保证父类和子类能够共享特征。

有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dqDMBbH9-1597203291241)(C:\Users\吴淼杰\Desktop\笔记\Java\Java09 面向对象下二\image-20200811151437499.png)]

abstract:抽象的

abstract可以修饰的结构:类、方法

1.1 代码实例

public class AbstractTest{
    public static void main(String[] args){
        
        //Person p1 = new Person();
        //Cannot instantiate the type Person
        //一旦Person类抽象化了,就不能实例化了
        
    }
}

abstract class Person{
	
    //属性
    String name;
	int age;
	
    //构造器
	public Person(){
	
	}
	
	public Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	
    //方法
	public void eat(){
	
	}
	
	public void sleep(){
	
	}
    
    //抽象方法
    public abstract void eat();
    
    //toString重写
    public String toSting(){
        
    }
}

class Student extends Person{
    
    public Student(String name,int age){
		super(name,age);
        //this.name = name;
		//this.age = age;
	}
    
    //The type Student must implement the inherited abstract method Person.eat()
    public void eat(){
        
    }
    
}

1.2 abstract修饰类:抽象类

abstract class Person{

}
  1. 此类不能实例化
  2. 抽象类中一旦有构造器,便于子类实例化调用(super()加载父类)
  3. 开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作

1.3 abstract修饰方法:抽象方法

public abstract void eat();
  1. 抽象方法只有方法的声明,没有方法体

  2. 包含抽象方法的类,一定是一个抽象类。

    反之,抽象类中可以没有抽象方法的。

  3. 若子类重写了父类们中的所有的抽象方法后,此子类方可实例化

    若子类没有重写父类们中的所有抽象方法,则此子类也是一个抽象类,需要使用abstract修饰

1.4 例子

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bNvrtXhX-1597203291251)(C:\Users\吴淼杰\Desktop\笔记\Java\Java09 面向对象下二\image-20200811160543343.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fVflThaL-1597203291253)(C:\Users\吴淼杰\Desktop\笔记\Java\Java09 面向对象下二\image-20200811160633122.png)]

1.5 使用注意点

  1. abstract不能用来修饰:属性、构造器等
  2. abstract不能用来修饰私有方法、静态方法、final的方法、final的类

2 抽象类的匿名子类(只用一次)

相当于临时重写了Person类中的抽象方法

//创建了一个匿名子类的对象:p
Person p = new Person(){

​ public void eat(){

​ }

}

public class Test{
    public static void main(String[] args){
        
        method(new Stuent());//匿名对象
        
        Worker worker = new Worker();
        method1(worker);//非匿名的类、非匿名的对象
        method1(new Worker());//非匿名的类、匿名的对象
        
        //匿名子类的非匿名对象
        //创建了一个匿名子类的对象:p
        Person p = new Person(){
            public void eat(){
                System.out.println("Eat")}
        };
        method1(p);
        
        //匿名子类的匿名对象
        method1(new Person(){
            public void eat(){
                System.out.println("Eat")}
        })
        
    }
    
    public static void method(Student s){
        
    }
    
    public static void method1(Person p){
        p.eat();
    }
    
}

abstract class Person{
	
    //属性
    String name;
	int age;
	
    //构造器
	public Person(){
	
	}
	
	public Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	
    //方法
	public void sleep(){
	
	}
    
    //抽象方法
    public abstract void eat();

}

class Worker extends Person{
    
    public void eat(){
        
    }
    
}

class Student extends Person{
    
    public Student(String name,int age){
		super(name,age);
        //this.name = name;
		//this.age = age;
	}
    
    //The type Student must implement the inherited abstract method Person.eat()
    public void eat(){
        
    }
}

3 抽象类的应用:模板方法设计模式(TemplateMethod)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WMTb3v9T-1597203291258)(C:\Users\吴淼杰\Desktop\笔记\Java\Java09 面向对象下二\image-20200812020506307.png)]

public class TemplateTest{
    public static void main(String[] args){
        
        Template t = new SubTemplate();
        t.spendTime();
        
    }
}

abstract class Template{
	
    //计算某段代码执行需要花费的时间
    public void spendTime(){
        
        long start = System.currentTimeMillis();
        code();//不稳定的部分,一遍的部分
        long end = System.currentTimeMillis();
        System.out.println("花费的时间为:" + (end - start));
        
    }
    
    public abstract void code();

}

class SubTemplate extends Template{
    
    @Override
    public void code(){
        
        for(int i = 2;i <= 1000;i++){
            boolean isFlag = 
        }
        
    }
    
}

4 接口(interface)

4.1 概念

在这里插入图片描述
在这里插入图片描述

4.2 举例

在这里插入图片描述
在这里插入图片描述

4.3 接口的使用

  1. 接口使用interface来定义
  2. Java中,接口和类是并列的两个结构

4.4 接口的定义(定义接口中的成员)

4.4.1 JDK7及以前

只能定义全局常量抽象方法

  • 全局常量:public static final的。但是书写时可以省略
  • 抽象方法:public abstact的。
public class InterfaceTest{
    public static void main(String[] args){
        
        System.out.println(Flyable.MAX_SPEED);
        System.out.println(Flyable.MIN_SPEED);
        
        Plane plane = new Plane();
        plane.fly();
        
    }
}

interface Flyable{
    
    //全局常量
    public static final int MAX_SPEED = 7900;
    int MIN_SPEED = 1;
    //int Min_SPEED = 1;//前面被省略了public static final,默认有public static final 
    
    //抽象方法
    public abstact void fly();
    
    void stop();//省略了public abstact
    
}

class Plane implements Flyable{
    
    @Override
    public void fly(){
        System.out.println("飞机飞");
    }
    
    @Override
    public void stop(){
        System.out.println("飞机停");
    }
    
}
4.4.2 JDK8

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y1yR4tRg-1597203291268)(C:\Users\吴淼杰\Desktop\笔记\Java\Java09 面向对象下二\image-20200812094518429.png)]

除了定义全局常量抽象方法之外,还可以定义静态方法默认方法

  1. 接口中定义的静态方法,只能通过接口去调用

  2. 接口中定义的静态方法,可以通过实现类的对象去调用

    如果实现类重写了接口中的默认方法,调用时,仍然调用的是重写后的方法

  3. 如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的方法,那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数的方法 — 类优先原则

  4. 如果实现类中实现了多个接口,而这多个接口定义了同名同参数的默认方法,那么在实现类没有重写此方法的情况下,出错 — 接口冲突

    这就需要我们必须在实现类中重写此方法

  5. 如何在子类(或实现)中调用父类、接口中被重写的方法

    super.method3();//调用的是父类中声明的方法 CompareA.super.method3();//调用接口中的默认方法

public class SubClassTest{
    public static void main(String[] args){
        
        SubClass s = new SubClass();
        //s.method1();//The method method1() is undefined for the type SubClass
        //1.接口中定义的静态方法,只能通过接口来调用
        CompareA.method1();
        //2.接口中定义的静态方法,可以通过实现类的对象去调用
        //如果实现类重写了接口中的默认方法,调用时,仍然调用的是重写后的方法
        s.method2();//SubClass method2重写
        //3.如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的方法,那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数的方法 --- 类优先原则
        s.method3();//SuperClass父类方法method3
        
    }
}

public interface CompareA{
    
    //静态方法(可以直接通过接口调用)
    public static void metho1{
        System.out.println("可以定义静态方法");
    }
    
    //默认方法(实现类里调用)
    public default void method2{
        System.out.println("CompareA接口可以定义默认方法");
    }
    default void method3{//省略了public,默认是有的
        System.out.println("CompareA接口可以定义默认方法");
    }
}

public interface CompareB{
    
    default void method3{//省略了public,默认是有的
        System.out.println("CompareB接口mthod3");
    }
    
}

public class SuperClass{
    
    public void method3{
        System.out.println("SuperClass父类方法method3");
    }
    
}

class SubClass extends SuperClass implements CompareA,CompareB{
    
    @Override
    public default void method2{
        System.out.println("SubClass method2重写");
    }
    
    @Override
    public default void method3{
        System.out.println("SubClass method3重写");
    }
    
    //5.如何在子类(或实现)中调用父类、接口中被重写的方法
    public void myMethod(){
        method3();//自己定义的重写的方法
        super.method3();//调用的是父类中声明的方法 
        CompareA.super.method3();//调用接口中的默认方法
        CompareB.super.method3();
    }
    
}

4.5 知识点

  1. 接口中不能定义构造器(意味着接口不可以实例化)

  2. Java开发中,接口都通过让类去实现(interface)的方式来使用

    • 如果实现类覆盖了接口中的所有抽象方法,则此实现类就可以实例化
    • 如果实现类没有覆盖接口中的所有抽象方法,则此实现类仍未一个抽象类
  3. Java类可以实现多个接口(弥补了Java单继承性的局限性)

    格式:class AA extends BB implements CC,DD,EE

  4. 接口与接口之间可以继承,而且可以多继承

  5. 接口的具体使用,体现多态性

  6. 接口,实际上可以看作是一种规范

  7. 开发中,体会面向接口编程

    public class USBTest{
    	public static main(String[] args){
    		
            Computer com = new Computer();
            
            //1.创建了接口的【非匿名实现类】的【非匿名对象】
            Flash flash = new Flash();
            com.transferData(flash);//体现接口的多态性,填入接口的实现类
            //USB usb = new Flash();
            
            //2.创建了接口的【非匿名实现类】的【匿名对象】
            com.transferData(new Printer());
            
            //3.创建了接口的【匿名实现类】的【非匿名对象】
            USB phone = new USB(){
                @Override
        		public void start(){
            		System.out.println("手机开始工作");
        		}
        
        		@Override
        		public void end(){
            		System.out.println("手机结束工作");
        		}
            };
            com.transferData(phone);
            
            
            //4.创建了接口的【匿名实现类】的【匿名对象】
            com.transferData(new USB(){
                @Override
        		public void start(){
            		System.out.println("手机开始工作");
        		}
        
        		@Override
        		public void end(){
            		System.out.println("手机结束工作");
        		}
            })
    	}
    }
    
    interface USB{//接口实际上定义了一种规范
        int LENGTH = ?;
        int MAX_SPEED = 1024;
        int MIN_SPEED = 0;
        
        void start();
        
        void end();
    }
    
    class Flash interface USB{
        @Override
        public void start(){
            System.out.println("U盘开始工作");
        }
        
        @Override
        public void end(){
            System.out.println("U盘结束工作");
        }
    }
    
    class Printer interface USB{
        @Override
        public void start(){
            System.out.println("打印机开始工作");
        }
        
        @Override
        public void end(){
            System.out.println("打印机结束工作");
        }
    }
    
    class Computer{
        
        public void transferData(USB usb){//形参要是USB实现类的对象
            usb.start();
            System.out.println("具体传输数据的细节");
            usb.end();
        }
        
    }
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ml9Gpk93-1597203291270)(C:\Users\吴淼杰\Desktop\笔记\Java\Java09 面向对象下二\image-20200812053559983.png)]

5 抽象类与接口的异同

6 接口的应用:代理模式(Proxy)

在这里插入图片描述
在这里插入图片描述

//静态代理
public class NetWorkTest{
	public static main(String[] args){
		
        Server server = new Server();
        ProvyServer provyServer = new ProvyServer(server);
        //server.browse();//为什么不直接这样,因为还要做check();
        provyServer.browse();
            
    }
}

interface NetWork{
    
    public void browse();
    
}

//被代理类
class Server interface NetWork{
    
    @Override
    public void browse(){
    	System.out.println("真实的服务器访问网络");
    }
    
}

//代理类
class ProxyServer interface NetWork{
    
    private NetWork work;
    
    public ProxyServer(NetWork work){
        this.work = work
    }
    
    public void check(){
    	System.out.println("联网之前的检查工作");
    }
    
    @Override
    public void browse(){
    	check();
        work.browse();
    }
}

7 接口的应用:工厂模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QkwW7aEs-1597203291273)(C:\Users\吴淼杰\Desktop\笔记\Java\Java09 面向对象下二\image-20200812061511388.png)]

8 题目

8.1 直接父类与直接父类的相同x

就近原则

8.2 继承与接口的相同x

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aSJlshCZ-1597203291274)(C:\Users\吴淼杰\Desktop\笔记\Java\Java09 面向对象下二\image-20200812090854232.png)]

8.3 排错

在这里插入图片描述
在这里插入图片描述

8.4 包装类的比较

声明未包装类时(如:Double),可以调用包装类的方法比较大小(两个包装类是引用数据类型)

c1.compareTo(c2);

8.5 JDK8的接口特性

两接口有同名同参数方法,出错,重写才不出错

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Xe1mZkT-1597203291278)(C:\Users\吴淼杰\Desktop\笔记\Java\Java09 面向对象下二\image-20200812102824020.png)]

类优先原则

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QnQUlE99-1597203291279)(C:\Users\吴淼杰\Desktop\笔记\Java\Java09 面向对象下二\image-20200812103003206.png)]

调用接口中的默认方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iAfselew-1597203291281)(C:\Users\吴淼杰\Desktop\笔记\Java\Java09 面向对象下二\image-20200812103055371.png)]

9 类的成员之五:内部类

源码见,开发不常见

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KijnNuQB-1597203291282)(C:\Users\吴淼杰\Desktop\笔记\Java\Java09 面向对象下二\image-20200812103303490.png)]

内部类举例:

Person可用name,age修饰,还要有一个大脑修饰,不可放在Person外修饰,且用简单的String修饰差点意思,这时可以用内部类修饰

  1. Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类

9.1 内部类的分类

成员内部类(静态、非静态) VS 局部内部类(方法内、代码块内、构造器内)

public class InnerClassTest{
	public static main(String[] args){
		
        //9.2.1 如何实例化成员内部类的对象
        //创建Dog实例(静态成员内部类)
        Person.Dog dog = Person.Dog();//套娃
        dog.show();
        //创建Bird实例(非静态成员内部类)要有外部类的实例
        Person p = new Person();
        Person.Bird bird = p.new Bird();//奇葩
        bird.show();
            
    }
}

class Person{
    
    String name;
    int age;
    
    public void eat(){
        
    }
    
    //静态成员内部类
    abstract static class Dog{
        String name;
        int age;
        
        public void show(){
            
        }
    }
    
    //非静态成员内部类
    class Bird{
        String name;
        int age;
        
        public void show(){
            eat();
            //eat() == Person.this.eat();//套娃
        }
        
        public void display(String name){
            System.out.println(name);//方法的形参
            System.out.println(this.name);//内部类的属性
            System.out.println(Person.this.name);//外部类的属性
        }
    }
    
    
    //方法
    public void method(){
        //局部内部类
        class AA{
            
        }
    }
    
    //代码块
    {
        //局部内部类
        class BB{
            
        }
    }
    
    //构造器
    public Person(){
        //局部内部类
        class CC{
            
        }
    }
    
}
9.1.1 成员内部类

一方面,作为外部类的成员:

  1. 调用外部类的结构
  2. 可以被static修饰
  3. 可以被4种不同的权限修饰

另一方面,作为一个类:

  1. 类可以定义属性、方法、构造器等
  2. 可以被final修饰,表示此类不能被继承。不使用final,就可以被继承
  3. 可以被abstract修饰,不能被实例化了
9.1.2 局部内部类

9.2 关注如下的3个问题

9.2.1 如何实例化成员内部类的对象
//创建Dog实例(静态成员内部类)
Person.Dog dog = Person.Dog();//套娃
dog.show();
//创建Bird实例(非静态成员内部类)要有外部类的实例
Person p = new Person();
Person.Bird bird = p.new Bird();//奇葩
bird.show();
9.2.2 如何在成员内部类中区分调用外部类的结构
public void display(String name){
	System.out.println(name);//方法的形参
	System.out.println(this.name);//内部类的属性
	System.out.println(Person.this.name);//外部类的属性
}
9.2.3 开发中局部内部类的使用
public class InnerClassTest1{

    //1.
    //局部内部类
    //返回一个实现了Comparable接口的类的对象
    public Comparable getComparable(){
        
        //创建了一个实现了Comparable接口的类:局部内部类
        class MyComparable implements Comparable{
        	@Override
        	public int compareTo(Object o){
            	return 0;
        	}
    	}
        return new MyComparable();
    }
    
    //2.
    //局部内部类
    //返回一个实现了Comparable接口的类的对象
    public Comparable getComparable(){
        
        //匿名实现类的匿名对面
        return new Comparable(Object o){
            @Override
        	public int compareTo(Object o){
            	return 0;
        	}
        }
            
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值