【面向对象设计基础】接口

作者:gnuhpc
出处:http://www.cnblogs.com/gnuhpc/

a)使用场景:解决多重继承和Client需要多Service_Provider的支持。

b)典型UML:

 

image

 

c)举例:薪水计算类的设计

image

不同的类别有不同的薪水计算方法,那么getSalary方法可以抽象到一个接口SalaryCalculator内,这样在Client进行调用时就会有多态的效果:

image

public interface SalaryCalculator {
      public double getSalary();
}

public class Employee {
       SalaryCalculator empType;
       String name;

       public Employee(String s, SalaryCalculator c) {
             name = s;
             empType = c;
       }
       public void display() {
            System.out.println("Name=" + name);
            System.out.println("salary= " + empType.getSalary());
       }
}

 

public class CategoryA implements SalaryCalculator {
     double baseSalary;
     double OT;

     public CategoryA(double base, double overTime) {
          baseSalary = base;
          OT = overTime;
     }
     public double getSalary() {
          return (baseSalary + OT);
     }
}


public class CategoryB implements SalaryCalculator {
      double salesAmt;
      double baseSalary;
      final static double commission = 0.02;
      public CategoryB(double sa, double base) {
         baseSalary = base;
         salesAmt = sa;
      }
     public double getSalary() {
         return (baseSalary + (commission * salesAmt));
     }
}

 

public class MainApp {
     public static void main(String [] args) {
     SalaryCalculator c = new CategoryA(10000, 200);
     Employee e = new Employee ("Jennifer”,c);
     e.display();
     c = new CategoryB(20000, 800);
     e = new Employee ("Shania”,c);
     e.display();
     }  
}

 

 

补充问题:

 

1.为什么不支持多重继承:依据Sun的官方说法是,避免c++那样管理多重继承的层次关系而带来的复杂性(主要是在多态覆盖方法的时候采用的动态绑定机制),换成用接口来实现多重继承的大部分功能,一个类只能有一个父类,但可以有多个接口,以此对多继承提供了有力的支持。

 

2.类中声明了系统可以提供的服务,类似于电路中的模块,但是不包含具体的实现。要表达“这是我要完成的任务,除此之外的细节不归我操心”时就用接口,例如:
public interface Photographable{
public void takePhoto();
}

 

3.接口中的成员变量默认都是public、static、final类型,因此必须被显示初始化。方法默认都是public、abstract。这是必须遵守的。

 

4.接口没有构造方法,不能被实例化。与抽象类不同,接口不能提供任何具体实现。

 

5.一个接口不能实现另一个接口,但是它可以继承多个接口。例如:
public interface C extends A,B{
void methodC();
}

 

6.接口必须通过类来实现它的抽象方法,例如:
public class Glass implements Transparency{...}
要是一个类要实现某个接口时,它必须实现接口中所有的抽象方法,除非这个类被定义为抽象类。若想要修改一个interface但影响太大又不能修改,则可以声明一个新的interface来继承原来的interface,并在其中增加操作。然后在使用的时候还面向父接口的同时,加上instanceof去判断,然后进行强制类型转换——这是个蹩脚的设计,来对待蹩脚的问题。


7.允许定义接口类型的引用变量去引用实现了该接口的类的实例:
Transparency t=new Glass();

 

8.抽象类vs接口:这个问题最终归结于接口会不会变化、实现类是不是需要同时支持多个接口。抽象类与接口都是位于继承树的上方,都不能被实例化,都可以包含抽象方法。但前者可以提供默认实现,而后者则必须包含抽象方法。接口一旦确定就不能随意改动了,否则就带来太大的麻烦,所以接口一般被用来作为纯粹的规格描述。接口不要求它的实现类在语义上是同一种类型,所以要是非同类型的相同方法类型则使用接口,利于继承树的合理化。接口是系统最高层次的抽象类型。抽象类则是介于“抽象”和“实现”之间的半成品,抽象类力所能及地完成了部分实现。定制模式就是一种接口颗粒度细化的设计模式。抽象类是为了逻辑的封装,包含部分实现,同时要求子类必须按照某种方式实现。

 

抽象类为类型建模,接口类为能力建模,同样都是is-a关系,前者表示类型上的,后者表示具备能力上的。

 

9.针对接口设计的实质:接口用稳定性封装了易变化的部分,在实际的设计中,将稳定部分抽象为接口,然后将不稳定的具体实现设定为实现该接口的类,在方法中利用接口将变化封装起来作为传入参数,调用其中接口定义的方法即可,这个方法根本不知道具体的实现,只是作为封装变化的一个中转站。调用的时候直接传入一个想使用的具体实现类。

 

10)注意:一个类继承了一个父类,并且实现了多个接口,extends放在implement前边.

 

作者:gnuhpc
出处:http://www.cnblogs.com/gnuhpc/

原文地址:https://www.cnblogs.com/gnuhpc/p/2822376.html