第19条:接口只用于定义类型

当类实现接口时,接口就充可以引用这个类的实例的类型。因此,类实现了接口,就表明客户端可以对这个类的实例实施某些动作。为了任何其他目的而定义接口是不恰当的。

有一种接口被称为常量接口(constant interface),它不满足上面的条件。这种接口没有包含任何方法,它只包含静态的final域,每个域都导出一个常量。使用这些常量的类实现这个接口,以避免用类名来修饰常量名。下面是一个例子:

1 public interface PhysicalConstants {
2     static final double AVOGADROS_NUMBER = 6.02214199e23;
3     static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
4     static final double ELECTRON_MASS = 9.10938188e-31;
5 }

常量接口模式是对接口的不良使用。类在内部使用某些常量,这纯粹是实现细节。实现常量接口,会导致把这样的实现细节泄露到该类的导出API中。类实现常量接口,这对于这个类的用户来讲并没有什么价值。实际上,这样做反而会使他们更加糊涂。更糟糕的是,它代表了一种承诺:如果再将来的发行版本中,这个类被修改了,它不在需要使用这些常量了,它依然必须实现这个接口,以确保二进制兼容性。如果非final类实现了常量接口,它的所有子类的命名空间也会被接口中的常量所“污染”。

如果要导出常量,可以有几种合理的选择方案。如果这些常量与某个现有的类或者接口紧密相关,就应该把这些常量添加到这个类或者接口中。例如,在Java平台类库中所有的数值包装类,如Integer或Double,都导出了MIN_VALUE和MAX_VALUE常量。如果这些常量最好被看作枚举类型的成员,就应该用枚举类型(enum type)来导出这些常量。否则,应该使用不可实例化的工具类(utility class)来导出这些常量。下面的例子是前面的PhysicalConstants例子的工具类翻版:

1 public class PhysicalConstants {
2     private PhysicalConstant() {};
3     public static final double AVOGADROS_NUMBER = 6.02214199e23;
4     public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
5     public static final double ELECTRON_MASS = 9.10938188e-31;
6 }

工具类通常要求客户端要使用类名来修饰这些常量名,例如PhysicalConstants.AVOGADROS_NUMBER。如果大量利用工具类导出的常量,可以通过利用静态导入(static import)机制,避免用类名来修饰常量名,不过,静态导入机制是在Java发行版本1.5中才引入的。

简而言之,接口应该只被用来定义类型,它们不应该被用来导出常量。

原文地址:https://www.cnblogs.com/remote/p/10359213.html

时间: 02-08

第19条:接口只用于定义类型的相关文章

第十九条:接口只用于定义类型

当类实现接口时,接口就充当可以引用这个类的实例的类型.因此,类实现了接口,就表明客户端可以对这个类的实例实施接口中的方法. 为了任何其他目的而定义接口是不恰当的. 常量接口:接口中只有常量,定义这个接口,目的是为了让实现这个接口的类,使用定义的常量. 常量接口这种做法应该不被使用.同样的目的,我们可以专门定义个存放常量的工具类来完成. JDK中几个常量接口:ObjectStreamConstants接口 接口应该只被用来定义类型 ,它们不应该被用来导出常量.

第37条:用标记接口定义类型

标记接口是没有包含方法声明的接口,而只是指明一个类实现了具有某种属性的接口.考虑Serializable接口,通过实现这个接口,类表明它的实例可以被写到ObjectOutputStream. 标记接口相比标记注解的优点: 1.标记接口定义的类型是由被标记类的实例实现的:标记注解则没有定义这样的类型. 2. 可以被更精确地进行锁定.如果注解类型利用@Target(ElementType.TYPE)声明,它就可以被应用到任何类或者接口,假设有一个标记只是适用于特殊的接口实现,但它却可以被应用到类,如

Java定义接口变量为接收类型有什么好处(面向接口编程)

个人理解:定义接口变量为接收类型属于面向接口的编程,通过接口的抽象能减少类之间的耦合,增加可复用性. 面向接口编程: 一种规范约束 制定者(或者叫协调者),实现者(或者叫生产者),调用者(或者叫消费者). 接口本质上就是由制定者来协调实现者和调用者之间的关系. 只有实现者和调用者都遵循“面向接口编程”这个准则,制定者的协调目的才能达到. 接口的语义是can-do语义,表约束(Constraint). 像JDBC的规范API,不管你使用哪一套实现,我们使用的时候都是使用相同的API. 分离设计与实

第三条 私有化构造器或者枚举类型强化Singleton属性

1.5版本之前,我们通常实现单例模式有两种方式: 两种方法前提都是私有化构造器,然后通过不同的方式获取对象. 第一种:通过公共的静态变量获取 public class Elivs{ // 私有化构造器 private Elivs(){} // 通过静态私有变量保存对象 public static final Elivs INSTANCE = new Elivs(); } 第二种:通过静态方法获取 public class Elivs{ // 私有化构造器 private Elivs(){} //

《Effective Objective-C 2.0》—(第15-22条)—接口与API设计、深拷贝、浅拷贝

第15条:用前缀避免命名空间冲突 Objective-C没有其他语言内置的命名空间(namespace)机制.如果发生命名冲突程序连接时候,出现以下错误: duplicate symbol _OBJC_METACLASS_$_EOCTheClass in: build/something.o build/something_else.o duplicate symbol _OBJC_CLASS_$_EOCTheClass in: build/something.o build/something

抽象类和接口作为返回值类型的问题

1 /* 2 返回值类型 3 引用类型: 4 类:返回的是该类的对象 5 抽象类:返回的是该抽象类的子类对象 6 接口: 7 */ 8 abstract class Person { 9 public abstract void study(); 10 } 11 12 class PersonDemo { 13 public Person getPerson() { 14 //Person p = new Student(); 15 //return p; 16 17 return new St

利用接口实现多种数据库类型的灵活更换

当存在可能要更换数据库类型的时候,要考虑两个问题: 一,不同类型的数据库命名空间不一样,用到的函数名也不一样,尽管很相似: 二,有些SQL语句在不一样的数据库之间是不通用的! 那么要在更换数据库类型的时候,如何做到尽量少受因为上面两点而造成的影响呢?!利用接口,可以将第一点的影响降到最低!至于第二点, 可以将数据的操作尽量在数据库服务器端实现,这点的探讨不在本文研究范围内,在此也就不多说!下面主要就利用接口将第一点的影响降到最低这一点进行详细说 明. 首先,明确两点: 1, 无论哪种数据库类型,

为什么用C++写库 但是导出接口时 却定义了C的接口(李大哥告诉我的,我还没有理解,先记着吧。为以后查询方便,哈哈)

导出C接口 使其拥有使用范围最广的接口 和多方式支持.比如操作系统,用C++写,但是接口申明了#ifdef C plus plus,判断如果是C++代码 就导出C接口,windows 下微软的几乎所有接口都是这样导出的,linux也一样.举例说明,我们导出一个C++接口 接口函数如下:KERNEL_USER_API int UserLogin(LPCTSTR lpszUserName,LPCTSTR lpszPassword);   假设这是一个内核库 封装了所有方法   然后提供给界面程序调用

在命名空间下定义类型

如果定义的类型要用于其他.NET 语言,应该把它们放在命名空间下,而不是模块中.这是因为模块在被编译成 C# 或其他.NET 语言时,被处理成类,在模块中定义的任何类型都成为这个类型内部的类.虽然对于 C# 来说,这并不是什么大问题,但是,如果用命名空间代替模块,C# 客户端代码看起来会更清晰.这是因为在 C# 中,只用using 语句导入(open)命名空间,而如果是在模块中的类型,在 C# 中使用时,就必须把模块名作为前缀. 让我们看一下这样的例子.下面的例子定义了类TheClass,它是在