抽象类、接口与枚举

抽象类 abstract class

场景

    public abstract class MockBusiness {
	    public void fun1(){
     
    	public abstract void fun2();// 依赖于第三方实现

        public void fun3(){
        }
}

1.抽象类的使用场景:

在业务实现中,有一个或多个功能需要依赖于第三方实现,则把该些功能设计为抽象方法,则该类就为抽象类。

2.定义:

含有抽象方法的类,就是抽象类

方法只有声明,没有实现(没有方法体)。

abstract void grow();
abstract void grow(){}  // 有实现,空实现  error 

3. 抽象类的定义以及使用规则:

抽象类不一定含有抽象方法。
包含一个抽象方法的类必须是抽象类;
抽象类和抽象方法都要使用 abstract 关键字声明;
抽象方法只需声明不要实现;
抽象类必须被子类继承,子类(如果不是抽象类)必须覆写抽象类中的全部抽象方法;

抽象类不能被实例化,只能引用子类的对象。 向上转换
抽象类作为参数,传的是子类的对象  
抽象类作为返回值,返回的是子类的对象。
  • 示例:

    public abstract class MockBusiness {

      public MockBusiness(){}
    
      public void fun1(){
    
      }
      public void fun2(){
    
      }
      public abstract void fun3() ;//fun3() 依赖于其他类【子类】实现
    
      public void fun4(){
    
      }
    

    }

  • 子类

    /**
    *
    alt + enter implements 父类的抽象方法
    */
    public class A extends MockBusiness {

      @Override
      public void fun3() {
          //子类实现父类方法(语法上是重写)
      }
    

    }

    public abstract class B extends MockBusiness {
    //abstract fun3();
    abstract void fun7();
    }

    //实现子类C 要实现 所有父类 的所有抽象方法
    public class C extends B {

      @Override
      void fun7() {
    
      }
    
      @Override
      public void fun3() {
    
      }
    

    }

4. 注意:final abstract 不能结合使用

final类不能有子类;

抽象类必须有子类;



抽象类中能定义构造方法么?
答:能的;因为抽象类依然使用的是类的继承关系,且抽象类中
也存在各个属性,所以子类在实例化之前肯定是对父类进行的实例化的。
  • 补充:

    1.什么时候覆盖toString()方法?

    Person p = new Person();

    System.out.println§;

    java会自动调用toString()方法;

    但是结果不是我们想要的,因为Object类的toString()方法总是返回对象的

    实现类类名 + @ + hashCode值。

    我们希望的是能够打印出p的全名来,这时就希望能覆盖toString()方法,
    因为重写toString方法之后,会优先调用自己的toString()方法。

应用中的抽象类:

若子类的方法实现都不一样,父类就没必要具体实现这些方法,父类把这些方法定义为抽象方法,子类根据自己的需求各自实现

**
 * 银行账户
 * 业务中:new Account() 错误
 * new SavingAccount()
 * new CreditAccount()
 *
 */
public abstract class Account {
    //取款 储蓄账户、信用账户 取款方式都不一样,
   public abstract double withdrwa(double money);

}

public class SavingAccount extends Account {
    @Override
    public double withdrwa(double money) {
        return 0;
    }
}

public class CreditAccount extends Account {
    @Override
    public double withdrwa(double money) {
        return 0;
    }
}

接口存在的意义:

1、安全、严密性(封装):接口是实现软件松耦合的重要手段,它描叙了系统对外的所有服务,而不涉及任何具体的实现细节。这样就比较安全、严密一些(一般软件服务商考虑的比较多)。

2、维护、拓展性:比如你要做一个画板程序,其中里面有一个面板类,主要负责绘画功能,
       然后你就这样定义了这个类,可是在不久将来,你突然发现这个类满足不了你了,然后你又要重新设计这个类,更糟糕是你可能要放弃这个类,那么其他地方可能有引用他,这样修改起来很麻烦,如果你一开始定义一个接口,把绘制功能放在接口里,然后定义类时实现这个接口,然后你只要用这个接口去引用实现它的类就行了,以后要换的话只不过是引用另一个类而已,这样就达到维护、拓展的方便性。

3、简单、规范性:如果一个项目比较庞大,
       那么就需要一个能理清所有业务的架构师来定义一些主要的接口,
       这些接口不仅告诉开发人员你需要实现那些业务,
       而且也将命名规范限制住了(防止一些开发人员随便命名导致别的程序员无法看明白)。

4、重要性:在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了Java强大的 面向对象能力。

接口定义:就是两个对象相互通信的约束或规则

接口:

纯抽象类,是类能够做什么的合约,方法只有声明,没有实现。
	是一种特殊类,里面全部是由全局常量和公共的抽象方法组成。

如何定义接口?

	 interface 接口名称{
		 // 全局常量;
		 // 抽象方法;
	 }



 Ps:接口中定义的成员变量 ,成员方法
 	public interface A{
      public static final int AGE= 18;
      public abstract void fly();
    }

 等价于:(完全一样)
 public interface A{
        int i= 1;
        void fly();
  }
  
// 注意:  
 	final、private、static、protected void fly();//非法定义接口的方法
  • 示例:

接口:

public interface Cpu {
    //全局常量
    public static final int PRODUCT_YEAR = 2019;

    //抽象方法
    public abstract void cpuRun();
    public abstract void cpuStop();
}
实现子类 HpCpu
public class HpCpu implements Cpu {
    @Override
    public void cpuRun() {

    }

    @Override
    public void cpuStop() {

    }
}
实现子类 HuaWeiCpu
//实现CPU 必须具备的功能
public class HuaWeiCpu implements Cpu{
    @Override
    public void cpuRun() {

    }

    @Override
    public void cpuStop() {

    }
}

接口使用注意:

1. 接口的使用也必须有子类,子类必须覆盖全部抽象方法,implements关键字实现, 一个子类可以实现多个接口,则子类如果不是抽象类的话,
	   一定要覆写接口中的全部方法。
2. 继承抽象类实现接口: 
一个子类可以同时继承抽象类和实现接口
    	语法:
 			class 子类 extends 抽象类 implements 接口A,接口B...{}
 3.接口的继承:
  一个接口不能继承抽象类,但是能通过extends关键字同时继承多个接口,实现
  接口的多继承。

 语法:
 	interface 子接口 extends 父接口A,父接口B,...{}
 	接口中的抽象方法可以不加入abstract,而抽象类中的抽象方法必须有abstract关键字声明;

4.一个类只能继承一个父类,但是可以同时实现多个接口;
  一个接口可以同时继承多个接口,以实现接口的多继承;
  接口和抽象类一样,都必须依靠子类;
  一个抽象类可以实现多个接口,但是一个接口不能继承一个抽象类。
  5、如果某个类实现了某个接口,那么我们就说,这个类具备这个接口所定义的功能。从语法角度来说,和继承类似

6、接口不能被实例化,只能引用子类的对象(接口作为参数或者返回值类型)

7、什么时候使用抽象类和接口?

什么时候使用抽象类和接口?

应用:
	一个类中一部分功能需要依赖于其他类实现,则把这些方法定义为抽象方法,该类 为 抽象类
	组件与组件之间(模块与模块之间)的通讯,使用接口 (保证业务内部实现不被暴露,降低模块之间的耦合性)
语法:
	public abstract class A{
        public void fun1(){}
        public abstract void fun2();        
	}
	
public interface B{
    //全局常量
    public static final int X = 10;
    //抽象方法
    public abstract void fun3();     
    
}

public interface A {
    public void fun1();
}

 interface  B{
    public void fun2();
}

//接口 可以多继承
interface  C extends A,B{
    public  void fun3();

}


class D{

}
// 继承 + 实现多接口
class E extends  D implements A,B,C{

    @Override
    public void fun1() {

    }

    @Override
    public void fun2() {

    }

    @Override
    public void fun3() {

    }
}

枚举 enum

JDK5.0新特性之枚举:

1、枚举分析

        是一种数据类型,是一个类,是一个final类,
        其对象是现成的固定的,其父类是java.lang.Enum。

2.在JDK5.0之前,用此方式实现枚举

     例子:自己完成一个枚举类;
     class Season1{
           public static final Season1 SPRING = new Season1();
           public static final Season1 SUMMER = new Season1();
           public static final Season1 AUTUMN = new Season1();
           public static final Season1 WINTER = new Season1(); 
           private Season1(){}    //构造方法私有
     }

或者

	class Season1{
         public static final Season1 SPRING = new Season1(“春天”);
         public static final Season1 SUMMER = new Season1(“夏天”);
         public static final Season1 AUTUMN = new Season1(“秋天”);
         public static final Season1 WINTER = new Season1(“冬天”);
         private String name; 
         private Season1(){  this.name=name}    //构造方法私有
         public String getName(){
             return name;
         }
      }

3. JDK5.0支持枚举

语法格式:

   修饰符 enum Season2{
          //枚举值
          //属性
          //构造器(私有)
          //方法
   }
  • 示例

     enum Season2{
           SPRING,   SUMMER,  AUTUMN,WINTER
     }
    

或者

   enum Season{
          //枚举值
         SPRING(“春天”),
         SUMMER(“夏天”),
         AUTUMN(“秋天”),
         WINTER(“冬天”);
         //属性
         String name;
         //构造器
         Season(String name){
             this.name=name;
         }
         //方法
         public String getName(){
             return this.name;
         }
   }
  • 注意:

     1)枚举可以很好的控制参数的种类和数量,保证必须按照程序员安排来选择;
     2)类不能继承枚举,枚举也不能继承类,但可以实现接口;
     3)枚举是一个final类,但是enum中却可以有抽象方法,抽象方法是由枚举值实现的;即这些
             抽象方法只能通过定义好的几个对象来实现,而且只能通过匿名的内部类的方法来实现。
     4)枚举写在最前面,否则编译错误
     5)实现带有构造器的枚举:
         a. 通过括号赋值,而且必须带有一个参构造器和一个属性跟方法,否则编译出;
         b. 赋值必须都赋值或都不赋值,不能一部分赋值一部分不赋值;如果不赋值则不能写构造器,赋值编译也出错.
    
      6)构造器默认也只能是private, 从而保证构造函数只能在内部使用
      7)枚举是一种类型,用于定义变量,以限制变量的赋值;赋值时通过“枚举名.值”取得枚举中的值(例如:ColorEnum colorEnum = ColorEnum.black;(switch case))
      8)for-each遍历枚举
      9)获取枚举的个数
      10)获取枚举的索引位置,默认从0开始
      11)枚举默认实现了java.lang.Comparable接口
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值