Day10--面向对象5-1

5   Day10--面向对象5

5.1      接口

5.1.1 概念

Java里面由于不允许多重继承,所以如果要实现多个类的功能,则可以通过实现多个接口来实现。

Java接口和Java抽象类代表的就是抽象类型,就是我们需要提出的抽象层的具体表现。OOP面向对象的编程,如果要提高程序的复用率,增加程序的可维护性,可扩展性,就必须是面向接口的编程,面向抽象的编程,正确地使用接口、抽象类这些太有用的抽象类型做为java结构层次上的顶层。

interface 接口名{  代码…  }

5.1.2     特点

1、 接口中都是抽象方法

2、 通过interface关键字创建接口

3、 通过implements让子类来实现

4、 可以理解成,接口是一个特殊的抽象类

5、 接口突破了java的单继承的局限性

6、 接口和类之间可以多实现,接口和接口之间可以多继承

7、 接口是对外暴露的规则,是一套开发规范

8、 接口提高了程序的功能扩展,降低了耦合性

5.1.3     入门案例

package day10;

public class T {

       public static void main(String[] args) {

              Zi z = new Zi();

              z.study();

              z.teach();

       }

}

interface Fu{

       public abstract void study();

       public abstract void teach();

}

//实现+重写

class Zi implements Fu{

       public void study(){

              System.out.println("Zi..study()");

       }

       public void teach(){

              System.out.println("Zi..teach()");

       }

}

5.2  接口的用法

5.2.1     构造方法

接口里是没有构造方法的。

在创建实现类的对象时默认的super(),是调用的默认Object的无参构造。

interface Fu{//定义一个接口

       public abstract void show();

       //Interfaces cannot have constructors

       /*public Fu(){

              System.out.println("Fu.Fu()");

       }*/

}

 

5.2.2     成员变量

接口里没有成员变量,都是常量。所以,你定义一个变量没有写修饰符时,默认会加上:

public static final

package day10;

//构造函数,成员方法,成员变量

public interface Test7_Fu {

 

}

interface Fu2{//定义一个接口

      

       //int num=10;//1,成员变量

       //static int num=10;//2,默认就是静态的

       //final static int num=10;//3,默认就是final的

       public final static int num=10;//4,默认就是public的

 

class Zi7 implements Fu2{

 

}

 

class Test7Demoo{

       public static void main(String[] args) {

              Zi7 znew Zi7();

              //The final field Fu2.num cannot be assigned

              //z.num=30;//默认是final的,不能修改值

              System.out.println(z.num);

              System.out.println(Fu2.num);

       }

}

5.2.3     接口的成员方法

接口里的方法,默认就都是抽象的,如果你不写明是abstract的,那会自动补齐。

例如:public abstract void save

package cn.tedu.interfacedemo;

//这个类用来测试接口的使用

public class Test2_UseInter {

    public static void main(String[] args) {

       //测试

//     Inter2 in = new Inter2();//3、接口不能创建对象

       Inter2 in = new Inter2Impl();

//     in.count = 20 ;//4、是最终的,The final field Inter2.count cannot be assigned

       System.out.println(  in.COUNT   );

       System.out.println(  Inter2.COUNT );//5、是静态的

      

       in.get();

       in.update();

    }

}

//创建接口

interface Inter2{

    //1、接口里可以有构造方法吗?   ---  不能!!

//  public Inter2() {}

   

    //2、接口里可以有成员变量吗?   ---   没有!!

//public static final  int count = 10;//简写,接口会为变量自动拼接  public static final

    int COUNT = 10 ; 

   

    //3、接口里可以有成员方法吗?  --- 可以,但都是抽象方法!!

    //public abstract void update() ; // 简写,接口会为方法自动拼接 public abstract

    void update() ; // 简写,接口会为方法自动拼接 public abstract

    void get() ;

}

class Inter2Impl  implements  Inter2{

    @Override

    public void update() {

       System.out.println("update()...");

    }

    @Override

    public void get() {

       System.out.println("get()...");

    }

}

5.3      接口的复杂用法

Java中单继承的局限性通过接口可以解决。

接口可以多继承也可以多实现,甚至可以继承的同时多实现。

package cn.tedu.interfacedemo;

 

//这个类用来测试接口的复杂用法:多继承多实现

public class Test4_ComInter {

    public static void main(String[] args) {

       Interface1 in = new Interface1Impl();

       in.save();

       in.update();

    }

}

//创建接口1

interface Interface1{

    void save();

    void update();

}

//创建接口2

interface Interface2{

    void get();

    void delete();

}

//1、打破了java单继承的局限性,因为接口之间可以多继承,多个接口之间逗号隔开

interface Interface3 extends Interface1,Interface2{

    void add();

}

//3、接口还可以多实现吗??---可以多实现,只不过接口之间逗号隔开

class ManyImpl implements  Interface1,Interface2{

    public void save() {}

    public void update() {}

    public void get() {}

    public void delete() {}

}

//4、接口可以继承的同时,多实现?? --

class MoreImple extends ManyImpl  implements Interface1,Interface2  {

}

//2、创建实现类,使用3号接口的功能,需要重写几个方法呢??---同时重写1号和2号和3号接口里的所有功能

class Interface3Impl  implements Interface3{

    @Override

    public void save() {  }

    @Override

    public void update() {  }

    @Override

    public void get() {  }

    @Override

    public void delete() {   }

    @Override

    public void add() {  }

}

//TODO 创建实现类

class Interface1Impl implements Interface1{

    @Override

    public void save() {

       System.out.println("save()...");

    }

    @Override

    public void update() {

       System.out.println("update()...");

    }

}

5.4  总结

1、类和类的关系:继承 extends / 单继承 / 单根继承

    -- 继承的意义:为了提高代码的复用性,减少了代码的编写提高开发效率。

    -- 方法重写的意义:在不修改父类源码的前提下,在子类中重写业务,从此使用的就是重写后的功能。

       -- 要求子类的方法声明和父类一样,只要改方法体。

    -- 有了继承有了重写就产生了多态,多态的意义:为了统一程序的调用标准,标准就是父类。

    -- 多态 也就是向上转型/向上造型。

    -- 向下造型的意义:很少用,相当于想要使用子类的特殊功能,还不如直接创建子类对象简单。

    -- class A extends B

    -- 其中,A和B都是类,A是子类,B是父类,A就拥有了B的所有功能(除了私有的和构造方法)

 

    -- 其他知识点:this 和super  ,构造方法,各种代码块...

 

2、类和接口关系:实现implements  / 单实现 / 多实现

    -- class A implements B,C

    -- 其中,A是实现类,B和C是接口

    -- 要求A 可以把 B 和C 接口里的所有 抽象方法 都重写掉,否则 A 就是抽象类

    -- 接口不能创建对象

    -- 接口里没有构造方法,接口里都是常量,接口里都是抽象方法

 

3、接口和接口关系:继承extends / 单继承 / 多继承

    -- 接口的多继承的关系,打破了java单继承的局限性

    -- interface A  extends  B,C

    -- 其中,A B C 都是接口,A是子接口,同时拥有B和C接口里的所有功能

    -- class AImpl implements  A

    -- 要求AImpl需要重写A接口里的所有方法(是包含B和C接口的所有方法),否则就是抽象类

 

4、接口和抽象类的区别!!!

    -- 相同点:都是抽象层,都不能实例化                      

    -- 不同点:

       -- 1、抽象类用abstract关键字描述,接口用interface

       -- 2、子类和抽象类之间是extends关系,实现类和接口之间是implements关系

       -- 3、抽象类中 可以  有构造方法 ,接口里 不能 出现 构造方法

       -- 4、抽象类里可以有 变量,接口里没有变量全都是静态的常量

       -- 5、接口里定义常量的语法:public static final String NAME="jack",会为变量自动拼接public static final

       -- 6、抽象类里 可以有普通方法  也可以有 抽象方法,接口都是抽象方法

       -- 7、抽象类和子类之间是继承关系,而且java中,只支持单继承

       -- 8、接口突破了java单继承的局限性,因为接口可以多继承也可以多实现,甚至可以继承的同时多实现

       -- 9、接口的复杂用法

           -- 多继承: interface A  extends  B,C  其中A是子接口,同时拥有自己的和BC的功能

           -- 多实现: class AImpl implements M,N,O,P 其中AImpl是实现类,需要同时重写MNOP的所有抽象方法,否则就是一个抽象类

           -- 继承的同时多实现: class AImpl extends Object implements M,N 一定是先继承后实现

5.5  设计模式

Java中有23 种设计模式,本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性,以及类的关联关系和组合关系的充分理解。

当然,软件设计模式只是一个引导,在实际的软件开发中,必须根据具体的需求来选择。

1、 对于简单的程序,可能写一个简单的算法要比引入某种设计模式更加容易。

2、 但是对于大型项目开发或者框架设计,用设计模式来组织代码显然更好。

5.5.1     单例设计模式概念

单例模式可以说是大多数开发人员在实际中使用最多的,常见的Spring默认创建的bean就是单例模式的。

单例模式有很多好处,比如可节约系统内存空间,控制资源的使用。

其中单例模式最重要的是确保对象只有一个。

简单来说,保证一个类在内存中的对象就一个。

RunTime就是典型的单例设计,我们通过对RunTime类的分析,一窥究竟。

5.5.2     源码剖析

/**

 * Every Java application has a single instance of class

 * <code>Runtime</code> that allows the application to interface with

 * the environment in which the application is running. The current

 * runtime can be obtained from the <code>getRuntime</code> method.

 * <p>

 * An application cannot create its own instance of this class.

 *

 * @author  unascribed

 * @see     java.lang.Runtime#getRuntime()

 * @since   JDK1.0

 */

RunTime.java

package java.lang;

 

public class Runtime {

    //1、创建静态的全局唯一的对象

    private static Runtime currentRuntime = new Runtime();

 

    //2、私有构造方法,

    /** Don't let anyone else instantiate this class */

    private Runtime() {}

 

   

 

//3、通过自定义的静态方法获取实例

    public static Runtime getRuntime() {

        return currentRuntime;

    }

}

5.5.3     饿汉式

目的:控制外界创建对象的个数只能创建1个对象

开发步骤:

1、 私有化构造方法

2、 在类的内部创建好对象

3、 对外界提供一个公共的get(),返回一个已经准备好的对象

package cn.tedu.single;

//测试单例设计模式 

public class Test8_Single {

    public static void main(String[] args) {

       Single s = Single.get();

       Single s1 = Single.get();

      

       //get()多少次,内存中使用的都是同一个对象

       System.out.println(s);//cn.tedu.single.Single@15db9742

       System.out.println(s1);//cn.tedu.single.Single@15db9742

    }

}

class Single{

//  1、私有化构造方法,不让外界直接new

    private Single() {}

   

//  2、在类的内部,创建好对象

    //static :静态只能调用静态

    static private  Single s = new Single();

   

//  3、对外界提供一个公共的get(),返回一个已经准备好的对象

//static是为了外界不通过对象访问而是通过类名直接方法 

    static public Single get(){

       //注意:静态只能调用静态

       return s;

    }

}

5.5.4     懒汉式

class Single{

//  1、私有化构造方法,不让外界直接new

    private Single() {}

   

//  2、在类的内部,创建好对象

    //static :静态只能调用静态

    static private  Single s = null;

   

//  3、对外界提供一个公共的get(),返回一个已经准备好的对象

//static是为了外界不通过对象访问而是通过类名直接方法 

synchronized  static public Single get(){

       //注意:静态只能调用静态

       if(s==null){

           s = new Single();//会有安全问题

}

       return s;

    }

}

5.6  拓展

5.6.1     abstract注意事项

抽象方法要求子类继承后必须重写。那么,abstract关键字不可以和哪些关键字一起使用呢?以下关键字,在抽象类中。用是可以用的,只是没有意义了。

1、 private:被私有化后,子类无法重写,与abstract相违背。

2、 static:静态的,优先于对象存在。抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。

3、 final:被final修饰后,无法重写,与abstract相违背。

 

5.6.2     接口和抽象类的区别

1、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。

2、抽象类要被子类继承,接口要被类实现。

3、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现

4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。

5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。

6、抽象方法只能申明,不能实现,接口是设计的结果 ,抽象类是重构的结果

7、抽象类里可以没有抽象方法,如果要扩展抽象类的新方法,子类将很容易的就能得到这些新方法。

8、如果一个类里有抽象方法,那么这个类只能是抽象类

9、抽象方法要被实现,所以不能是静态的,也不能是私有的。

10、接口可继承接口,并可多继承接口,但类只能单根继承。

5.6.3     设计学员示例

具体事物:培优班学员,高手班学员

共性:姓名,学号,学习方法,休假方法

利用面向抽象 、 面向接口的编程思想,完成程序设计。

 

5.6.4     了解软件设计的开闭原则OCP

开放功能扩展,关闭源码修改。等

开闭原则的英文全称是Open Close Principle,缩写是OCP,它是Java世界里最基础的设计原则,它指导我们如何建立一个稳定的、灵活的系统。

开闭原则的定义是:软件中的对象(类、模块、函数等)应该对于扩展是开放的,但是对于修改是封闭的。

开闭原则,是一种设计模式,随着面向对象程序设计的思想,应运而生。

开,指的是可以在源代码的基础上进行扩展,比如继承,接口,抽象类等。在JAVA中,之所以用继承,是在可以直接调用类库的前提下,对其功能进行扩展。不需要应用者去了解封装类的内部逻辑就可以做开发。

闭:指不允许对原有的代码进行修改。以免影响其他现有功能,造成功能瘫痪。

 

package cn.tedu.oop;

public class ActTecher implements Teacher{

    @Override
    public void ready() {
        System.out.println("高手班老师在备课");
    }
    @Override
    public void teach() {
        System.out.println("高手班老师在讲课");
    }
}
 

package cn.tedu.oop;
//描述培优班老师的事物
public class CgbTeacher implements Teacher{

    @Override
    public void ready() {
        System.out.println("培优班老师在备课");
    }
    @Override
    public void teach() {
        System.out.println("培优班老师在讲课");
    }
}
 

 

package cn.tedu.oop;
//把子类间的共性功能,向上提取,形成父类
//要不要把父类修饰成抽象层,是程序设计的结果
interface Teacher {

     void ready();//接口特有的简写形式 会为你的自动拼接 public abstract
     void teach();
}
 

package cn.tedu.oop;
//测试接口
/*接口和抽象类一样都不能被实例化(new)
 * */
public class Test1_Interface {

    public static void main(String[] args) {
        Demo demo=new DemoImpl();
        demo.eat();//用了接口里的抽象方法声明,实现类的方法体
        demo.game();
        demo.hi();

    }

}
/*抽象类里可以有抽象方法(必须被abstract修饰,也可以有普通方法(方法体)
 * 接口里的方法都是抽象方法
 * 通过interface关键字定义接口,语法:interface 接口名
 * 接口为方法的编写提供了简写方式,会自动拼接abstract public
 * */
//定义接口
interface Demo {
    abstract public void eat();
    abstract public void game();
    //在jdk1.8里允许接口出现普通方法,要求被static或者default修饰
    void hi();
}
//abstract class DemoImpl implements Demo{//现在是实现类实现接口
 class DemoImpl implements Demo{//现在是实现类实现接口
    //实现接口后,由于接口里面都是抽象方法,所以需要全部重写,否则都是抽象类
    @Override
     public void eat() {
        System.out.println("eat()...."); 
     };
     @Override
    public void game() {
        System.out.println("game()...."); 
    };
    @Override
    public void hi() {
        System.out.println("hi()....");
    };
}

 

package cn.tedu.oop;
//测试接口
/*接口里没有构造方法
 * 接口里没有变量都是常量
 * 接口里都是抽象方法(jdk1.8可以有特殊的普通方法)
 * 接口里的常量可以简写,会自动拼接public static final
 * 接口里的方法可以简写,会自动拼接public abstract
 * */
public class Test2_Interface2 {

    public static void main(String[] args) {
        //接口不能被实例化(new)
        //new Inter();
        Inter in=new InterImpl();
        
        System.out.println(in.age);//10
        System.out.println(Inter.age);//10
        String desc=in.save();
        System.out.println(desc);
        in.delete(10);

    }

}
//接口 构造方法
interface Inter{
    //接口里不叫出现构造方法
//    public Inter() {
//        
//    }
    //接口里的变量,会自动拼接public static final把变量变成常量
    //接口里没有变量 把变量变成常量
    int age=10;
    //简写会自动拼接abstract public
//    abstract public void save();
//    abstract public void delete();
    String save();//简写形式
    void delete(int id);
}
//接口的实现类,要么重写所有抽象方法,要么是一个抽象类
class InterImpl implements Inter{
    public InterImpl() {
        super();//调用Object里的默认存在的无参构造
    }
    //在进行方法重写时,要有足够的权限,接口里的所有资源默认权限是public
    @Override
     public String save() {
        return "保存成功";
     };
     @Override
     public void delete(int id) {
         System.out.println("delete()....."+id); 
     };
}

 

package cn.tedu.oop;

import java.io.IOException;
import java.io.Reader;

//测试接口的复杂用法
//接口和类之间可以多实现,接口和接口之间可以多继承
public class Test3_Interface3 {

    public static void main(String[] args) {
        Inter2 i=new Inter2Impl();
        i.save();
        i.update();
        i.get();
        i.delete(4);

    }

}

interface Inter1{
    void save();
}
interface Inter3{
    void update();
    void get();
}
//实现类可以在继承的同时,多实现
class Impl2 extends Reader implements Inter1,Inter3{

    @Override
    public void update() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void get() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void save() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public int read(char[] cbuf, int off, int len) throws IOException {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void close() throws IOException {
        // TODO Auto-generated method stub
        
    }
    
}

//接口和实现类之间是--实现关系,而且可以多实现
//需要同时重写多个抽象方法,否则就是一个抽象类
class Impl implements Inter1,Inter3{

    @Override
    public void update() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void get() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void save() {
        // TODO Auto-generated method stub
        
    }
    
}

//2号接口想用1号和3号接口的功能,接口和接口间--是继承关系
interface Inter2 extends Inter1,Inter3 {
    void delete(int id);
}
//想要使用2号接口的功能,找一个实现类来实现接口
class Inter2Impl implements Inter2{

    @Override
    public void save() {
        // TODO Auto-generated method stub
        System.out.println(1);
    }

    @Override
    public void update() {
        // TODO Auto-generated method stub
        System.out.println(2);
    }

    @Override
    public void get() {
        // TODO Auto-generated method stub
        System.out.println(3);
    }

    @Override
    public void delete(int id) {
        // TODO Auto-generated method stub
        System.out.println(4);
    }
    
}
 

 

package cn.tedu.oop;
//测试程序设计
public class Test4_Design {

    public static void main(String[] args) {
        //接口和抽象类一样,不可以被实例化
        //创建多态对象测试 --多态体现的是调用标准
        Teacher t=new CgbTeacher();

        //标准就是父类,只能用父类提供的功能
        t.ready();
        t.teach();
        
        Teacher t2=new ActTecher();
        t2.ready();
        t2.teach();
    }

}
 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值