A rule of thumb about Interface vs Abstract Class

最近在翻阅Hadoop早期的jira list,对于一些重要的jira,会有很多贡献者的详细讨论,包括Doug Cutting, Tom White, Arun Murthy, Owen O'Malley等一批Hadoop领军人物的思想、观点,具有极强的学习价值。

今天在阅读Hadoop-3412和HADOOP-1230,当中Doug Cutting阐述了如何选择Interface和Abstract Class的观点。虽然这是个老生常谈的问题,但是Cutting作为极有经验的工程师,多个开源项目的创始者,从平台API evolution这个角度来讨论,很有参考性。

Cutting在HADOOP-1230中的原话如下:

The strategy here is to remove stuff that is likely to evolve from interfaces that users implement, so that we canchange it without breaking user implementations

Note that, in general, interfaces are much more difficult to evolve than abstract base classes, and should thus only be used when "mixin" behavior is required, e.g., when one needs to be able to add an interface to an existing class. For example, interfaces like Serializeable and Writable are great, since folks might need to have a class that implements both, which wouldn't be possible if they were abstract base classes. 

Some folks seem to believe that interfaces are somehow 'cleaner' and should be used for all public facing APIs. But that's not true: interfaces are limited to a subset of what abstract base classes can do, andan abstract class's ability to provide default implementations of methods greatly facilitates API evolution. Again (at the risk of sounding repetitive), the only advantage of interfaces is that a class can implement more than one of them

So, as we revisit our core APIs that users implement for the purpose of making them more easily backward compatible,we should use abstract base classes in place of interfaces whenever it is clear that multi-inheritance is not a requirement.


可以看到,Cutting的观点很明确,除非你要有mixing behaviour,也就是说要多继承,否则总是选择abstract class。本质的原因是abstract class可以提供default implementation,当你想要对某个API做修改时,它提供了更大的灵活性,使得你不需要改API interface,从而保持向后兼容性。

举个例子,假如你有一个API class如下:

abstract class JobInProgressListener {
	  public void jobAdded(JobInProgress job) throws IOException{
	  	//do nothing
	  }
}

如果未来你想要做修改,比如增加一个参数,你可以不用动原来的interface,而是增加一个overloaded方法,并且让原来的方法用默认参数调用新方法:

abstract class JobInProgressListener {
	  public void jobAdded(JobInProgress job) throws IOException{
		  jobAdded(job, new Configuration());
	  }
	  
	  public void jobAdded(JobInProgress job, Configuration conf) throws IOException{
		  //do something
	  }
}
如果JobInProgressListener是interface,你只能改变原来contract,从而break原来的客户代码。



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值