抽象类与抽象方法
抽象类(abstract)
- 抽象方法:只给出方法定义而没有具体实现的方法被称为抽象方法,抽象方法是没有方法体的,在代码的表达上就是没有“{}”。使用 abstract 修饰符来表示抽象方法和抽象类。
- 抽象类:包含抽象方法的类叫做抽象类(如果在类的方法声明中使用abstract修饰符,表明该方法是一个抽象方法,它需要在子类实现。如果一个类包含抽象方法,则这个类也是抽象类,必须使用abstract修饰符,并且不能实例化。 )
- 注意,抽象类除了包含抽象方法外,还可以包含具体的变量和具体的方法。类即使不包含抽象方法,也可以被声明为抽象类,防止被实例化。如果从一个抽象类继承,并想创建该新类的对象,那么就必须实现所有的基类中的抽象方法,否则自己也会变成抽象类.
接口(interface)
- 接口作用:定义规范,解耦合
只要一个方法操作的是类而非接口,那么你就只能使用这个类及其子类.如果你想要将这个方法应用于不在此继承结构中的某个类,那么你就会触霉头了.接口可以在很大程度上放宽这种限制,因此,它使得我们可以编写复用性更好的代码.
package package9;
public class Processor {
public String name(){
return getClass().getSimpleName();
}
Object process(Object input){
return input;
}
}
public class Upcase extends Processor{
Object process(Object input){
return ((String)input).toUpperCase();
}
}
public class Downcase extends Processor {
Object process(Object input){
return ((String)input).toLowerCase();
}
}
public class Splitter extends Processor {
Object process(Object input){
return Arrays.toString(((String)input).split(" "));
}
}
public class Apply {
public static void process(Processor p,Object s){
System.out.println("Using Processor "+p.name());
System.out.println(p.process(s));
}
public static String s ="Disagreement with beliefs is by definition incorrect";
public static void main(String[] args) {
process(new Upcase(),s);
process(new Downcase(),s);
process(new Splitter(),s);
}
}
//结果
Using Processor Upcase
DISAGREEMENT WITH BELIEFS IS BY DEFINITION INCORRECT
Using Processor Downcase
disagreement with beliefs is by definition incorrect
Using Processor Splitter
[Disagreement, with, beliefs, is, by, definition, incorrect]
Apply.process()方法可以接受任何类型的Processor,并将其应用到一个Object对象上,然后打印结果.像本例这样,创建一个能够根据所传参数对象的不同而具有不同行为的方法,被称为策略设计模式.这类方法包含所要执行的算法中固定不变的部分,而”策略”包含变化的部分.策略就是传递进去的参数对象,它包含要执行的代码.这里Processor 对象就是一个策略,在main()中可以看到有三种不同类型的策略应用到了String类型的s对象上
- 适配器设计模式:适配器中的代码将接受你所拥有的接口,并产生你所需要的接口
package package3;
public interface Processor {
String name();
Object process(Object input);
}
public class FilterAdapter implements Processor {//适配器
Filter filter;
public FilterAdapter(Filter filter) {
this.filter = filter;
}
@Override
public String name() {
return filter.name();
}
@Override
public Waveform process(Object input) {
return filter.process((Waveform)input);
}
}
public class Filter {
public String name(){
return getClass().getSimpleName();
}
public Waveform process(Waveform input){
return input;
}
}
public class LowPass extends Filter {
double cutoff;
public LowPass(double cutoff) {
this.cutoff = cutoff;
}
public Waveform process(Waveform input){
return input;
}
}
public class HighPass extends Filter {
double cutoff;
public HighPass(double cutoff) {
this.cutoff = cutoff;
}
public Waveform process(Waveform input){
return input;
}
}
public class BandPass extends Filter {
double lowCutoff,highCutoff;
public BandPass(double lowCutoff, double highCutoff) {
this.lowCutoff = lowCutoff;
this.highCutoff = highCutoff;
}
public Waveform process(Waveform input){
return input;
}
}
public class Waveform {
private static long counter;
private final long id=counter++;
public String toString(){
return "Waveform "+id;
}
}
public class Apply {
public static void process(Processor p,Object s){
System.out.println("Using Processor "+p.name());
System.out.println(p.process(s));
}
}
//结果
Using Processor LowPass
Waveform 0
Using Processor HighPass
Waveform 0
Using Processor BandPass
Waveform 0
这种使用适配器的方式中,FilterAdapter 的构造器接受你所拥有的接口Filter,然后生成具有你所需要的Processor接口对象.你可能还注意到FilterAdapter 类中用到了代理.接口从具体实现中解耦使得接口可以应用于多种不同的实现,因此代码更具可复用性.
java中多继承
- 类是单继承,接口是多继承
- 当一个具体类和多个接口组合到一起时,具体类必须放在前面,后面跟着的才是接口(否则编译器会报错).
- 该如何选择接口和抽象类?
如果要创建不带任何方法定义和成员变量的基类,那么就应该选择接口而不是抽象类.事实上,如果知道某事物应该成为一个基类,那么第一选择应该是使它成为一个接口.