1.接口和内部类我们提供了一种将接口与实现分离的更加结构化的方法。
2.抽象类,普通的类与接口之间的一种中庸之道。尽管在构建具有某些未实现方法的类时,你的第一想法可能是创建接口,但是抽象类仍然是用于此目的的一种重要而必须的工具。因为你不可能总是使用纯接口。
1.通用接口,建立诸如Instrument(乐器)这个通用接口的唯一理由是,不同的子类可以用不同的方式表示此接口。通用接口建立起来一种基本形式,以此表示所有导出类的共同部分。
2.另一种说法是将Instrument类称作抽象基类或简称抽象类。如果我们只有一个像Instrument的抽象类,那么该类的对象几乎没有任何意义。我们创建抽象类是希望通过这个通用接口操纵一系列类。因此 Instrument只是表示了一个接口,没有具体的实现内容,因此创建一个Instrument对象没有什么意义,并且我们还可能想阻止使用者这样做。通过让Instrument中的所有方法都产生错误,就可以实现这个目的。但是这样做会将错误信息延迟到运行时才获得,并且需要在客户端进行可靠,详尽的测试。所以最好是在编译时捕获这些问题->Java提供了抽象方法的机制,不完整的,仅有声明而没有方法体,如 abstract void f();
3.包含抽象方法的类叫做抽象类。如果一个类包含一个或多个抽象方法,该类必须被限定为抽象的,否则编译器报错。如果一个抽象类不完整,那么当我们试图产生该类的对象时,编译器会怎么处理。由于为抽象类创建对象是不安全的,所以我们会从编译器那里得到一条出错信息。这样,编译器会确保抽象类的纯粹性,我们不必担心会误用它。
4.如果从一个抽象类继承,并想创建该类的对象,那么就必须为基类的所有抽象方法提供方法定义,如果不这样做,可以选择不做,那么导出类也是抽象类,且编译器会强制我们用abstract关键字来限制这个类。
5.我们也可能创建一个没有任何抽象方法的抽象类,考虑这种情况,如果有一个类,让其包含任何abstracat方法都显得没有任何实际意义,而且我们也想阻止产生这个类的任何对象,那么这样做就很有用了。
6.创建抽象类和抽象方法很有用,因为他们可以使类的抽象性明确起来,并告诉用户和编译器打算怎么样来使用他们。抽象类还是很有用的重构工具,因为他们使得我们可以很容易的将公共方法沿着继承层次向上移动。
3.inte易做图ce关键字使抽象的概念更向前迈进了一步。abstract关键字允许人们在类中创建一个或多个没有任何定义的方法,提供了接口部分,而没有提供任何相应的具体实现。这些实现是由类的继承者创建的.inte易做图ce这个关键字产生一个完全抽象的类,它根本就没有提供任何具体实现。接口只提供了形式,而未提供任何具体实现。
1.一个接口表示,所有实现了该特定接口的类看起来都像这样。因此任何使用某特定接口的代码都知道可以调用该接口的哪些方法,而且仅需要知道这些。因此接口被用来建立类与类之间的协议。protocol.
3.inte易做图ce不仅仅是一个极度抽象的类,因为它允许人们通过创建一个能够被向上转型为多种基类的类型,来实现某种类似多重继承变种的特性。
4.接口也可以包含域,不过这些域隐式的是static和final的。可以选择在接口中显示的将方法声明为public的,但即使你不这么做,他们也是public的,因此,当要实现一个接口时,在接口中被定义的方法必须被定义为public的。否则他们只得到默认的包访问权限,这样在方法被继承的过程中 ,其可访问权限就被降低了。这是Java编译器所不允许的。
注:不仅仅是接口,对于继承覆盖的方法也不能降低可访问权限,即 Cannot reduce the visibility of the inherited method.但是我们可以增加可访问权限,比如基类方法是default,而导出类的覆盖方法则可以将访问权限提升至public.
4.只要一个方法操作的是类而不是接口,那么你就只能使用这个类及其子类,如果你想要将这个方法应用于不再此继承结构的某个类,那么你就会触霉头了。接口可以在很大程度上放宽这种限制,因此他们可以使我们可以编写可复用性更好的代码。
1.创建一个能够根据所传递的对象的参数不同而具有不同行为的方法,被称为策略设计模式。这类方法包含的所要执行的算法中固定不变的部分,而策略包含变化的部分,策略就是传递进去的参数对象 ,它包含要执行的代码。
2.将接口从具体实现中解耦使得接口可以应用于多种不同的具体实现,因此代码也就更具可复用性。
5.接口不仅仅是只是一种更纯粹形式的抽象类,它的目标比这要求更高。因为接口是没有任何具体实现的,也就是说没有任何与接口相关的存储;因此也就无法阻止多个接口的组合。这一点是很有价值的,因为你有时需要去表示“一个x是一个a和一个b以及一个c”。在c++中,组合多个类接口的行为被称作为多重继承(C++菱形问题,即B,C同时继承了接口A,D多重继承B,C,这样在调用A中的方法的时候,无法知道该方法究竟是B中的还是C中的)。它可能会使你背负很沉重的包袱,因为每一个类都有一个具体实现。
注:Java中接口不会有这样的问题,当你实现多个接口的时候。因为接口是没有实现的,这样菱形问题就不会对编译器造成困扰,因为都是没有实现的。即如接口B和接口C继承结合A,而实现类D实现了接口B和C,此时D的实现类中实现具体方法,因为所有的接口都是无实现的,所以编译器不会困扰,因为调用的肯定是实现的具体类的方法。因为具体类必须实现接口中未实现的方法。当然使用抽象类也是不行的,因为抽象类中也可以定义具体的方法。
1.当通过一个具体类和多个接口组合到一起的时候,这个具体类必须放在前面,后面跟着的才是接口,否则编译报错。
注:个人觉得这条规定可能是防止歧义的出现,比如正常的形式是A extends B implements C,D 如果换做:A implements C,D extends B的话,肯定会有歧义的,是c或D extends B?所以说编译器强制这样规定。
2.使用接口的核心原因:
1.为了能够向上转型为多个基类型以及由此而带来的灵活性。
2.然而使用接口的第二个原因却是与抽象基类相同,防止客户端程序员创建该类的对象,并确保这仅仅是创建一个接口。这就带了一个问题:我们应该使用接口还是抽象类?如果我们要创建不带任何方法定义和成员变量的基类,那么就应该选择接口而不是抽象类。事实上,如果知道某事物应该成为一个基类,那么第一选择应该是使它成为一个接口。
3.通过继承来扩展接口
4.一定要注意组合接口时的名字冲突问题->在打算组合的不同接口中使用相同的方法名通常会造成代码可读性的混乱,因为覆盖,实现,重载令人不愉快的搅在了一起,而且重载方法仅通过返回类型是区分不开的。请尽量避免这种情况。
6.适配接口:
1.接口最吸引人的原因就是允许同一个接口具有不同的具体实现。在简单的情况下,它的体现形式通常是一个接受接口类型的方法,而该接口的实现和向该方法传递的对象则取决于方法的使用者。因此接口的一种常见用法是策略设计模式。此时你编写一个执行某些操作的方法,而该方法将接受一个同样是你指定的接口,你主要就是要声明,“你可以用任何你想要的对象来调用我的方法,只要你的对象遵循我的接口”。这使你的方法更加灵活,通用并更具复用性。如Scanner的构造器参数Readable接口,通过这种方式,Scanner可以作用于更多的类型,只要你创建一个新类,并且让它成为Readable即可。
假设你有一个还未实现Readable接口的类B,怎么样才能让Scanner作用于它呢?-使用适配器模式,A extends B implements Readable接口即可。即被适配的类A可以通过继承B和实现Readable的类实现。因此,通过使用inte易做图ce关键字提供的伪多重继承机制,我们可以生成既是B又是Readable接口的新类A.
这种方式,我们可以在任何现有类之上添加新的接口,所以这意味着让方法接受接口类型,如{@link Scanner};是一种让任何类都可以对该方法进行适配的方式。这是使用接口而不是类的强大之处。
7.接口中的域:
因为你放入接口中的任何域都自动是static和final的,所以接口就成为了一种很便捷的用来创建常量组的工具。在Java SE5之前,这是产生于C/C++的enum(枚举类型)具有相同效果的类的唯一途径。有了Java SE5,你就可以使用更加强大而且灵活的enum关键字,因此用接口群组常量已经显得没什么意义了。
1.初始化接口中定义的域
1.在接口中定义的域不能是空final,但是可以被非常量表达式初始化。因为域是static的,所以它们就可以在类第一次被加载时初始化。这发生在任何域首次被访问时。
注:域不是接口的一部分,它们的值被存储在该接口的静态存储区域内。
8.嵌套接口
1.接口可以嵌套在类中或其他接口中。这揭示了许多非常有趣的特性。
注:嵌套的private接口,实现一个private接口只是一个形式,它可以强制该接口中的方法定义不要添加任何类型信息,也就是说
补充:软件开发 , Java ,