问一个很基础的问题,为什么这样可以java抽象类实现接口直接访问接口的方法

C++的”接口与实现分离“实现方法 - CSDN博客
&&&&&&& 让我们从stackoverflow上一个同学的问题来开始。问题的原型是这样的(原问题见:):
&&&&&&& Portaljacker:“有一个类A, 有一些共有成员函数和私有数据,如下所示。”
&&&&&&& “可是我不想让使用这个类的使用者看到我的私有数据,应该怎么做?可能是因为担心别人嘲笑我给变量起的名字太难听!哎,可是这关他们什么事呢!我试过把这三个成员变量放进另一个头文件中,就像下面那样,可是编译器报错- - 我该怎么办?!”
&&&&&&& 刚看到这个问题的时候,觉得它很幼稚。首先,C++一个类的定义必须包含该类所有的成员函数和变量,而不像一个名字空间里的不同函数那样可以自由分布在不同的源文件中。其次,这些私有成员即使对调用者可见,又怎么样?反正它们是私有的,用户怎么也不可能直接访问它们。
&&&&&&& 然而,我错了。
&&&&&&& Portaljacker的这个需要实际上是很合情合理的。试想,调用者一般是这样使用类A的。
// main.cpp
#include &A.h&
int main()
X x = a.getX();
Y y = a.getY();
Z z = a.getZ();
&&&&&&& 通常情况下调用者必须要包含A的定义所在的头文件才能顺利通过编译,也就是说建立了一个编译依赖关系:main.cpp -& A.h。这样,任何A.h文件中的变化都将导致main.cpp重新编译,即使改变的只是类A中的私有变量(比如名称改变)。这非常糟糕,因为一个类的私有数据属于它的实现细节(implementation
details),理想情况下应该隐藏起来,它的变化对于调用者不可见。哦,不知道你是否曾经遇到过这样一个工程,里面有成百上千的源文件。你只是改变了一个小小的头文件,结果发现项目中的大多数文件都重新编译,几分钟都没有编译完。
&&&&&&& 其实Portaljacker提出了一个很好的问题。问题的关键在于如何把实现的细节隐藏起来。这样,调用者既不会看到任何类内部的实现,也不会因为实现的任何改变而被迫重新编译。
&&&&&&& 在讨论问题的解决方法之前,有必要回过头来看看为什么Portaljacker同学的方法行不通。他是把同一个类的共有成员和私有成员风的定义分别放到了两个同名类的定义中(见上)。
&&&&&&& 我听到了,你说肯定不行。没错,为什么呢?”因为类的定义不能分割开。。“ 好吧,可是为什么呢?”C++就是这样的,常识!“ 资深一些的程序员甚至会翻到C++标准的某一页说,”喏,这就是标准“。我们中的很多人(包括我),学习一门语言的时候都是书上(或者老师)说什么就是什么,只要掌握了正确使用就行,很少有人会去想一下这规则背后的原因是什么。
&&&&&&& 回到正题。C++之所以不允许分割类定义的一大原因就是编译期需要确定对象的大小。考虑上面的main函数,在类定义分割开的情况下,这段代码将无法编译。因为编译器在编译”A a&的时候需要知道对象a有多大,而这个信息是通过查看A的定义得来的。而此时类的私有成员并不在其中,编译器将无法确定a的大小。注意,Java中并不存在这样的问题,因为Java所有的对象默认都是引用,类似于C++中的指针,编译期并不需要知道对象的大小。
接口与实现的分离
&&&&&&& 好了,现在让我们回到需要解决的问题上:
不希望使用者可以看到类内部的实现(比如有多少个私有数据,它们是什么类型,名字是什么等等)。除了接口,任何类的改变不应引起调用者的重新编译。
&&&&&&& 解决这些问题的方法就是恰当地将实现隐藏起来。为了完整性,我们来看看几个常见的接口与实现分离的技术,它们对于信息隐藏的支持力度是不一样的,也不是都能解决以上所有的问题。
一、使用私有成员
&&&&&&& 类的接口作为共有,所有的实现细节作为私有。这也是C++面向对象思想的精髓。通过将所有实现封装成私有,这样当类发生改变时,调用者不需要改变任何代码,除非类的公共接口发生了变化。然而,这样的分离只是最初步的,因为它可能会导致调用者重新编译,即使共有接口没有发生变化。
#include &X.h&
#include &Y.h&
#include &Z.h&
// 接口部分公有
// 实现部分私有
二、依赖对象的声明(declaration)而非定义(definition)
&&&&&&& 在前一种方法中,类A与X,Y,Z之间是紧耦合的关系。如果类A使用指针而非对象的话,类A并不需要包含X,Y,Z的定义,简单的向前声明(forward declaration)就可以。
&&&&&&& 这样,当X,Y或者Z发生变化的时候,A的调用者(main.cpp)不需要重新编译,这样可以有效阻止级联依赖的发生。在前一种方法中,若X改变,包含A.h的所有源文件都需要重新编译。注意,在声明一个函数的时候,即使函数的参数或者返回值中有传值拷贝,也不需要对应类的定义(上例中,不需要包含X,Y,Z的头文件)。只有当函数实现的时候才需要。
三、Pimpl模式
&&&&&&& 一个更好的方法是把一个类所有的实现细节都“代理”给另一个类来完成,而自己只负责提供接口。接口的实现则是通过调用Impl类的对应函数来实现。Scott Meyers称这是“真正意义上接口与实现的分离”。
// AImpl.h
class AImpl
// 可能的实现: X getX() { return pImpl-&getX(); }
std::tr1::shared_ptr&AImpl& pI
&&&&&&& 我们来看一下,这种方法能否满足我们的两个要求。首先,因为任何实现细节都是封装在AImpl类中,所以对于调用端来说是不可见的。其次,只要A的接口没有变化,调用端都不需要重新编译。很好!当然,天下没有免费的午餐,这种方法也是需要付出代价的。代价就是多了一个AImpl类需要维护,并且每次调用A的接口都将导致对于AImpl相应接口的间接调用。所以,遇到这样的问题,想一想,效率和数据的封装,哪个对于你的代码更重要。
四、Interface类
&&&&&&& 另一个能够同时满足两个需求的方法是使用接口类,也就是不包含私有数据的抽象类。调用端首先获得一个AConcrete对象的指针,然后通过接口指针A*来进行操作。这种方法的代价是可能会多一个VPTR,指向虚表。
virtual ~A();
virtual X getX() = 0;
virtual Y getY() = 0;
virtual Z getZ() = 0;
class AConcrete: public A
尽量依赖对象的声明而不是定义,这样的松耦合可以有效降低编译时的依赖。能够完全隐藏类的实现,并减少编译依赖的两种方法:Pimpl、Interface。一道Java基础程序,问一下题中为什么接口可以实例化呢_百度知道
一道Java基础程序,问一下题中为什么接口可以实例化呢
).printInfo() interface A{ public void printInfo();}class X{ public void fun1(){这是怎么回事?为什么在X类中实例化了; }}接口不是不能实例化吗;
) }public void fun2(A a){af&quot.fun2(new A{
public void printInfo(){
sysout(&quot?fun2()方法中的参数定义了A a=new A()
fun2(new A(){
public void printInfo() {
S); }}; }};asfas&/public class NoInnerClassDemo02 { public static void main(String args[]) {
new X(); }class X { public void fun2(A a) {
}).printInfo().println(& &#47:interface A { public void printInfo()我又采取了另一种表达方式
提问者采纳
public void printInfo(){
sysout(&quot。创建匿名内部类这种方法;af&quot,它可以访问接口中的数据;
}}这就是创造一个匿名内部类,经常用在“事件”的监听代码中,并且它覆盖了接口中的抽象函数,它没有自己的名字,而是直接使用它所实现的接口的名字;)
提问者评价
一看你的就明白了,O(∩_∩)O谢谢
其他类似问题
为您推荐:
实例化的相关知识
其他2条回答
接口是不能直接实例化的但是你的一个匿名类实现了接口 你把它赋给一个声明了接口的变量就没问题了这样就是用接口回调
this.fun2(new A{
public void printInfo(){
sysout(&af&);
}这是一个匿名内部类实现了接口;相当你传了一个接口的实现类对象作参数给方法;接口本身是不能实例化的;
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁█■为什么要用实现接口的类实例化接口呢? ?_百度知道
█■为什么要用实现接口的类实例化接口呢? ?
为什么要用实现接口的类实例化接口呢?这跟用 实现接口的类实例化自己 有什么区别啊?这么做有什么用呢?
提问者采纳
根据参数类型自动调用相关的实现接口的类,智能的选择出砖瓦的工作要哪个张三来干。呵呵,用声明的接口中的方法来代替这个方法体内的那些不同代码,说的通俗点就是有很多很多的方法,它们的大部分代码都相同,现在要盖个大房子?打个比喻,只是方法体内的几行代码不一样:有多个人叫张三,接口和泛型结合使用,接口它根据盖房子的不同任务(如砖瓦工),接口的用处是相当的广泛啊,就可以实现方法体内的编译时的多态性,会自动调用接口中的方法,当程序运行至此时,这时你必须知道哪个张三都干什么?你就可以只写一个方法,举个简单的例子来说呵呵,明白没,这时你怎么办,结合各个张三的实际情况,接口作用就在于此
其他类似问题
为您推荐:
其他3条回答
这就是接口的用处,相当于必须实现的某些功能很简单的一点,必须实现接口中的方法,因为接口的定义是一种对功能的一种约束.
实现接口的类 实例 = new 实现接口的类()// 这样用不好吗?
//这样已经不是好不好的问题了,这样的话,要接口有什么用?
//用接口就是让实例和实现类的耦合度降低。
//让程序更加容扩展。
以下是问题之外的知识,想看可以往下,不想看跳过。
接口 实例 = new 实现接口的类A()
接口 实例 = new 实现接口的类B()
接口 实例 = new 实现接口的类C()
这样的逻辑就是说,我们需要某个类,所以我们每次实例化它。
如果把 ABC这三个类,再用一个类封D装起来,会怎么样呢?
接口 实例 = D.A
接口 实例 = D.B
接口 实例 = D.C
我们还是需要某个类,但是,我们不需要每次都实例化了,只需要找D“拿”就行。
==========晕,不知不觉写了这么多,至于扩展性,你自己想吧======
TIPS:工厂模...
接口稳定啊 因为接口改了 继承它的类也得改 程序大了 改的就多了 所以没人愿意改的
实例化的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁JAVA中为什么要使用接口,继承接口不是还要重写方法吗?为什么不直接写那些方法呢?_百度知道
JAVA中为什么要使用接口,继承接口不是还要重写方法吗?为什么不直接写那些方法呢?
我的意思是为什么不直接写方法而要使用继承还要去重写其所有方法呢?
提问者采纳
有个读的抽象方法 那叫read()吧,就读U盘,因为你实现这个接口的类的方法名相同,但是实现内容不同我用接口来定义对象不就可以做到统一访问了吗。?接口主要针对多个类实现它来说的,要是只有一个类当然可以不用接口了,U盘类实现.read();这样a,然后mp3类实现,这样我用的时候用USB a=new 【类名】,你写哪个就用哪个了这个就叫统一访问,而这个名字可以从属性文件里读接口的最主要的作用是达到统一访问那么什么叫统一访问呢举个例子你这样想;要是我类名里写U盘,我做一个USB接口。,写mp3就读mp3,移动硬盘类实现
其他类似问题
为您推荐:
其他5条回答
内存?如果人家显卡的制造商升级显卡了 那主板生产商 就必须得重新制造主板以匹配显卡,它生产主板时,你显卡生产商自己搞定、声卡,JAVA 接口就是这个作用。所以 就只设定一个接口就好了,硬盘生产商就自己搞定硬盘的实现方法,我只给你们提供接口就OK了,那不是我主板生产商的事,肯定会有显卡,具体的实现方法、硬盘等等一大堆接口, 所以说这个是很不方便的,如果 全让主板商自己设定方法的话 那不是很麻烦,比如一家生产主板的 厂商这样跟你说吧
把常用的方法抽象出来,放到一个接口里,具体类按上接口后,再根据类的情况编写方法体。这是JAVA的重要编程思想:问题领域-&对象模型中的对象-&对象模型中的类-&对象模型中的父类。注意最后从 对象模型中的类-&对象模型中的父类
这一步,这样做的目的可提高两个系统间的松耦合。
去看一下设计模式,就知道接口是Java的主角
接口用来制定规则...
需要重写。
java的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁

我要回帖

更多关于 java 实现接口 的文章

 

随机推荐