任何抽象性都应该由需要驱动,有必要时才应该使用接口进行重构。 恰当的原则是有限
抽象类和方法
- 创建抽象类是为了通过接口操纵一系列类
- 若一个类包含一个或多个抽象方法,类本身也要为抽象类
- 抽象类不能实例化
- 继承抽象类的子类若要创建对象,则必须为基类所有抽象方法定义
- 阻止别人创建对象可在前+abstract
接口创建
- interface 关键字产生一个完全抽象的类,任何使用某特定接口的代码只能且仅需知道可以调用哪些该接口中的方法,而无法决定方法体。
- implements 使一个类遵循某个特定接口,提供接口实现。且来自接口中的方法必须被设置为public。 ```java interface Concept{ void idea1(); }
class Implementation implements Concept{ @Override public void idea1(){ System.out.println(“idea1”); } }
- **default:** 当实现接口却没有定义方法时,可以使用** default** 创建的方法体。
```java
interface Concept{
void idea1();
default void idea2(){
System.out.println("default idea2");
}
}
多继承:一个implementation可以实现多个接口,只要接口中所定义的函数方法签名(方法名+参数类型)[返回类型不行] 不同。
class MI implements One, Two, Three {}
多继承产生冲突时,需要通过Overrride 来解决冲突。
- super 关键字选择其中一个基类实现
- 直接覆写
静态方法:将工具功能置于接口,从而操作接口,成为通用工具。
public interface Operations {
void execute();
static void runOps(Operations... ops) {
for (Operations op: ops) {
op.execute();
}
}
//这个东西还蛮好玩
//runOps()使用可变参数列表,按照传入顺序运行不同实现的execute()
抽象类与接口比较
特性 | 接口 | 抽象类 |
---|---|---|
组合 | 新类可以组合多个接口 | 只能继承单一抽象类 |
状态 | 不能包含属性(除了静态属性,不支持对象状态) | 可以包含属性,非抽象方法可能引用这些属性 |
默认方法 和 抽象方法 | 不需要在子类中实现默认方法。默认方法可以引用其他接口的方法 | 必须在子类中实现抽象方法 |
构造器 | 没有构造器 | 可以有构造器 |
可见性 | 隐式 public | 可以是 protected 或友元 |
Java中的协变和逆变 。
LSP原则:所有引用基类的地方必须能透明地使用其子类的对象。
这里主要介绍后面两层定义:
- 当子类覆盖或实现父类的方法时,方法的形参要比父类的方法更加宽松。
- 当子类覆盖或实现父类的方法时,方法的返回值比父类更严格。
- Java常见类型转换的协变、逆变或不变性
- 泛型——不变
- 数组——协变
- 方法
- 普通情况:方法的形参是协变的、返回值是逆变的。
- 从Java1.5开始,子类覆盖父类方法的时候允许协变返回更为具体的类型。 ```java class Super { Number method(Number n) { … } }
class Sub extends Super { @Override Integer method(Number n) { … } }
3. 泛型中的通配符
- `<? extends>` 实现泛型协变
`List<? extends Number> list = new ArrayList();`
- `<? super>` 实现泛型逆变
`List<? super Number> list = new ArrayList`
4. 理解extends & super
```java
Number num = new Integer(1);
ArrayList<Number> list = new ArrayList<Integer>(); //type mismatch
List<? extends Number> list = new ArrayList<Number>();
list.add(new Integer(1)); //error
list.add(new Float(1.2f)); //error
由于 <? entends Number>
实行协变,表示list的类型为 Number与Number派生子类中的某一个,可以为Integer但不一定。故编译器在编译时无法确定这个list究竟为什么类型,所以会报错。
而改为 <? super Number>
后,表示list的类型为 Number与Number基类中的某一类型。**extends**
确定泛型上界, **super**
确定泛型下界。
- PECS (produce extends,consume super)
```java
// Wildcard type for parameter that serves as an E producer
public void pushAll(Iterable<? extends E> src) {
for (E e : src)
} //假设src为Iterablepush(e);
对象 //produce过程
// Wildcard type for parameter that serves as an E consumer public void popAll(Collection<? super E> dst) { while (!isEmpty()) dst.add(pop()); } //假设泛型为Collection