爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      实用抽象类和接口的区别

      首页 知识中心 软件开发 文章详情页

      实用抽象类和接口的区别

      2023-06-28 09:11:48 阅读次数:431

      class,抽象类,接口

      抽象类和接口又什么好处

      从这个问题我们可以衍生出两个问题:

      1.     为什么要用抽象类?

      2.      为什么要使用接口?

      企业单位在面试的时候经常会问到!

      答案综合考虑以下方面:

      1:强调不但应该具有什么能力,而且应该具有什么特性,并且一些能力有共同的处理细节的时候,可以用抽象类;
      2:只强调应该具有什么能力的时候,并且处理细节可能完全不同,就考虑用接口;
      3:抽象类考虑从上到下的继承和拥有,接口考虑从左到右的规范;

      ==============================================================

       

      使用接口定义行为,由于接口是特殊的抽象类,也就可以使用抽象类定义行为,抽象类同时能够实现行为;但仅是定义行为时,就可使用接口,因为接口能够更有效地分离定义与实现,为代码的维护和修改带来方便。

      ==============================================================

       

      1,  抽象类提供了一部分功能的实现,如果子类的功能实现和父类的功能实现是相同的,可以使用抽象

      2,  接口只规定了类的函数规范,没有具体实现。

      ==============================================================

       

      面向对象的经典是面向抽象编程。 

      所以,用抽象的型别统一类型,来进行操作,有利于以后的扩展,移植,复用!!

      ==============================================================

       

      其实抽象类的一个好处是类不能被实例化,最大的好处就是通过方法的覆盖来实现多态的属性。也就是运行期绑定

      ==============================================================

      我想用比较通俗的方法告诉你: 
        假如有两个程序员,两个在两个程序里都要用到一种功能,比如要取一个方法名。 
        甲自己做了一个方法叫getname,乙也作了一个方法叫qumingzi。如果两个人要去看对方的程序,那么

       这个方法要读懂是不是要有一个过程? 
        如果在公司里,有个抽象类,里面有个抽象方法getName,公司规定,凡遇到这样的问题就实现这个方法。  

       那么这两个人要读对方的代码是不是就容易了?? 

      ==============================================================

      假如很多人要买水果吃,吃的动作只有一个,但是有的人要用现金买,有的人用信用卡,有的人赊帐。要为每个人定义一个类,就要定义多个相同的吃的方法。如果定义一个抽象类,在里面实现吃的方法,再做一个买的抽象方法。那每个人的类都从这个抽象类派生下来,只要实现买的方法即可,吃的方法就可以直接用父类的方法了。如果要改吃的方法就不用改多个,只要改这个抽象类里的就行了。

      ==============================================================

      抽象类将事物的共性的东西提取出来,抽象成一个高层的类。子类由其继承时,也拥有了这个超类的属性和方法。---也就实现了代码的复用了。 
      子类中也可加上自己所特有的属性和方法。----也就实现了多态

      ==============================================================

      以学生为列,博士和硕士都是学生,那么学生就成为了一个父类了,他们都具有学生的特征,那些共同的特点就可以继承,实现代码重用 
        但是如果还有一种类型的学生,它既具有博士,又具有硕士的特点,那我岂不是要继承两个类,但是这两个类里又有很多相同的特征啊,那就现的代码冗余了,是吗? 
        那么我现在的目的就是要使它简洁,但是要达到那个效果,我就会用到接口,所谓的接口有两个含义 
        1。方法的集合 
        2。概念 
        第二中就是我们JAVA中用的,它把类中某些独有的方法用接口的形式表现出来,然后你就直接implement接口就是拉,再继承学生那个类,就可以拉  

      ==============================================================

      接口的好处之一: 
        就是可以多重继承, 而类不可以~ 

         
        子类,可以同是继承至一个接口和一个抽象基类 

      ==============================================================

      例子: 
             
          有以下类: 
          类(动物) 类(狗) 类(大象) 
                类(狗)和类(大象)是类(动物)的子类。 
                如果我希望别人只能创建类(狗)和类(大象)的对象,绝不希望别人能直接创建类(动物)的对象(直接创建类(动物)是无意义的,因为每一种动物都有它的真正类),于是我就可以把类(动物)做成抽象类

      ==============================================================

      就象建立房子的框架 
         
        里面的房间可以分别设计,但是框架不变 

      ==============================================================

      面向对象的经典是面向抽象编程 
         
        抽象的意思,就是你不必为每个插销定义一个插座。 
        你不用为每个CPU定义一个主板  
         
        抽象类和接口的意思,就是规范,大家都遵守。这样符合规范的东西,大家都不用了解各自的细节。插座不会了解插销怎么做的。插销也不必了解插座怎么做的。

      抽象类和接口的意思,就是规范,大家都遵守。这样符合规范的东西,大家都不用了解各自的细节。插座不会了解插销怎么做的。插销也不必了解插座怎么做的。

      ==============================================================

      JAVA是基于C/C++开发出来的,也可以称作是二者综合体的简化版,去处其中的一些过于复杂的控制功能或改由计算机自动处理。其中就包括去除了C++中的多重继承功能,而改由不计数量的接口来实现。  
        举个简单的例子:古希腊神话中的飞马。它既能奔跑(马的方法),又可以飞(鸟的方法)。在C++中可以通过多重继承来实现,但在JAVA中则必须通过接口来实现。或者继承马的方法,并实现一个鸟飞的接口。或者同时实现一个跑的接口和飞的接口。 
        接口具有良好可扩展性。有了跑和飞的两个借口,你可以轻松的做出飞猪,飞驴等具有类似功能的对象。 
        接口中不得实现任何方法。一个类一旦要实现一个接口,则必须实现改接口的所有方法,即使在该方法中不执行任何操作(即方法体内为空)。 
        接口与抽象类具有类似的功能。在使用上,一般接口用于定义比较普遍的方法,而抽象类主要用于比较具体的方法。

       

      面向对象的本质:万物皆对象!  
         
        封装:封装就是指利用抽象数据类型将数据和基于数据的操作封装在一起,数据被保护在抽象类型的内部,系统的其他部分只有通过包裹在数据外面的被授权的操作,才能够与这个抽象数据类型交流与交互! 
         
        继承:继承实际上是存在于面向对象程序中的两个类之间的关系。当一个类拥有另一个类的所有数据和操作时,就称这两个类之间具有继承关系! 
         
        多态:多态是指一个程序中同名的不同方法共存的情况。面向对象的程序中多态的情况有多种,可以通过子类对父类方法的覆盖实现多态,也可以利用重载在同一个类中定义多个同名的不同方法! 
         
        OO=Objects+Classes+Inheritance   +   Communication   With  messages  
        那还是教科书上说的, 
        多态,解释就是一个方法被多次构造,,经常出现在,继承关系类(抽象类,接口) 
        回忆一下接口使用   
        interface   I_Test{  
              public   void   Print   (){}  
        }  
        class   C_A   implment   I_Test{  
              public   void   Print(){  System.out.println("C_A")}  
        }  
        class   C_B   implment   I_Test{  
              public   void  Print(){System.out.println("C_B")}    
        }  
         
        再来看看class  Test{  
            public   void   main(){  
            I_Test   i=   new   C_A();  
                      i.Print();   //打印出C_A  
              i=   new   C_B();  
                      i.Print();//打印出C_B  
        }      
        //,"多态性是站在类的角度完成了接口与实现的分离",多态调用Print()方法,不知道能不能解释这句话,个人是这样一来理解的。 
         
        我个人认为“多态”不单是对父子类,接口,抽象类的理解。。关键还是要对  protect,private正确使用中去体味。 
        这样才能更好隔离,综合使用多态才会清晰。
         
         
        接口(Interface)是用来定义行为的!  
        抽象类(Abstract  Class)是用来实现行为的! 
        具体类()是用来执行行为的! 
         
         

         
                             支持多重继承,  支持抽象函数,  允许实现    ,允许创建实体,允许部分实现 
        interface           支持                        支持                  不允许              不允许                  不允许  
        abstract   class不支持                      支持                  允许                不允许                    允许 
        class                   不支持                不支持                    允许                  允许                    不允许  
         
         
        所以打算多继承,又并不想马上实现它的时候,就用接口。需要实现它的类需要。比如我上述例子中的Print(),,通常对应多个实现类的。(记得所有的方法都必须是public的,也可以用有static   final)  
         
        如果只需要实现部分的部分方法,又不需要全部实现,那就可以用抽象类。对于抽象方法,需要overrider  就是要重写一个方法来实现  所定义好的abstract  方法。(这个和接口一样) 
         
        如果全部实现,又全部要执行的。。那么就用直接类吧,父子关系一带被调用它的时候,比如子类继承了父类的方法时候,一调用就执行了。 
         

         
        其实,要从宏观上讲,那就牵涉到软件工程理论了。 
        个人看法: 
        事物的出现,总是有它出现的理由(需求)! 
        但是,事物的生存,需要有适应性(灵活)! 
        比如:长颈鹿,脖子长,这是个抽象的概念; 
        能吃草(是非肉食性动物的特征,接口)。 
         
        所以,当需要描述长颈鹿的时候,我们就可以用接口(非肉食性动物)和抽象(脖子长)的方法来定义它, 
        然后,具体是什么种类/或者颜色的长颈鹿,怎么个吃草法,这就是具体类了。  
         =============================================================

      经典解释是:使用了对象就叫基于对象,基于对象的基础上增加了继承从而变成了面向对象。 
         
        基于对象的最大特点就是封装,至于private,protected,public,并不是基于对象语言的必须要求。同时应该注意到的是,封装对于应用本身并没有提供太大的帮助;换句话说封装仅仅改变了方法的表达形式,除了析构函数能够提供一些资源安全上的保证,当然java没有析构函数。比如某些网络应用,包装了socket,然而必须的accept,listen,connect,read,write还是需要你自己去调用,只不过调用方式有所变化而已;更麻烦的是处理错误,可能的错误你必须完全接管,那就需要对问题本身有很深入的了解。基于对象让你不容易犯错误,但是不能改变对问题本身的理解。 
        于是出现了面向对象。继承,多态只是它的特点而已,一种表象。而关键优越性在于它可以改变对问题的认识。比如处处可见的画图的例子,p.Draw(),就能画出一个形状,都是Draw()方法,但是可以根据p的不同,动态选择。无可否认,这个是多态性的优越性的例子。然而继承又如何呢,可以这样说,如果不使用多态,继承就没有意义了。因为没有多态,继承事实上导致了较高层次的包装而已,与基于对象相同,它不能改变对问题本身的理解。很多时候继承被包裹所代替,COM的对象重用,就是典型的包裹,不过它叫聚集而已。类层次越深管理越困难。 
        面向对象提供了极大的灵活性,然而作为一个概念,外延太丰富,反而不容易把握。看看JFC的文档,实在太灵活了,感觉上这样那样几个东西拼合起来,窗口就可以做成了。事实却不是如此,你必须去了解layer,了解listener,了解很多东西,然后按照固定的规则进行拼装才能达到效果。简单说,看看javadoc的JFC文档,很难学会如何去实现一个可用的窗口应用。这一点明显比不上VB,其实这就和使用面向对象方法是为了接口易用性这一个基本原则背离了。外延被扩大化到难以接受的规模,这是使用面向对象方法很容易犯的毛病。而设计模式提供了一些方法缓和这些矛盾,比如用静态函数创建对象,私有构造,使得对象不能被任意创建,这就大大压缩了这些对象的外延。简单看看MessageDigest,可能在内部有md2,md4,md5,sha1的类供我创建对象,但是这些我都不让你看到,你只要知道一个MessageDigest就足够了,免得产生误会。  
         
        先说那么多了。 
         
         
        回复人:  Leemaasn(我给大家拜早年啦!新春快乐!!!)  (   )   信誉:101    2004-1-12   18:47:34    得分:0   
         
        zengpan_panpan()    
        牛,,,很彻底地分析了“何谓对象”!!! 
         
        回复人:  Leemaasn(我给大家拜早年啦!新春快乐!!!)  (   )   信誉:101    2004-1-12   20:40:23    得分:0   
         
        对于  zengpan_panpan()所说的“而关键优越性在于它可以改变对问题的认识。”!  
        个人看法如下: 
        通常,我们要使用一个对象的paint方法时,如果我们很具体的考虑这个Paint问题时,我们也许会从想要画什么开始。然后,考虑从该画什么东西,又考虑对于这个东西我们应该怎么画。。。。 
        一层层深入时,,,就会陷入到Windows底层API函数(我以Windows平台为例。),楼主是搞Delphi的。这点应该会明白。。。  
        如果只是简单几个类,那也无所谓,当大规模生产时,还是这么做,后果可想而知的(比如:Windows的MFC、或者VCL)。  
         
         
        如果我们以对象和接口的角度来考虑这个Paint问题。  
        那么,我们可以先定义好一些接口,比如paint这个接口。  
        然后再来设计对象,如果某个对象,需要paint这个方法,那么,我们可以让它实现paint这个接口。  
        具体怎么实现,这就是抽象类或者具体类的事情了。 
        然后,我们在其他地方调用这个对象的paint方法时,  
        我们就只需要按照这个paint这个接口的规定来调用就行了。  
         
         
        在这里,“改变对问题的认识”改变在什么地方呢?我们从对象的认识从一个具体到抽象、封装的方向变了。 
        就像人,又分为黄色人种、白色人种、黑色人种(抽象类)等。。。 
        中国人、印度人。。。(接口)等。。。 
         
        如果再抽象,可以看作:脊椎动物。。。。 
         
         
        哈,扯远了。。。 
         
         
        其实,真正的解答,应该请zengpan_panpan()来说明!!!  
        有请我们真正的主角。。。zengpan_panpan()隆重登场。。  
         
         
        回复人:  iamwls(-----魔高一尺,道高一丈-----)  (   )   信誉:96    2004-1-12   20:43:27    得分:0   
         
        to:   zengpan_panpan()    
         
        你所说的:使用了对象就叫基于对象,基于对象的基础上增加了继承从而变成了面向对象。 
         
        好象并不太准确 
         
        记得(好象是,呵呵)有人问JAVA的创始人:如果你想重来一次JAVA,你改变的是什么?  
        答:去掉继承 
         
        也许应该是增加了抽象多态,  从而变成了面向对象可能更准确点 
         
        回复人:  Leemaasn(我给大家拜早年啦!新春快乐!!!)  (   )   信誉:101    2004-1-12   21:06:27    得分:0   
         
        哈,好象这句话,我也有看过。。。 
        记得(好象是,呵呵)有人问JAVA的创始人:如果你想重来一次JAVA,你改变的是什么?  
        答:去掉继承 
         
         
        但没有继承,总觉得。。。似乎世界不太完美。。。。 
         
        回复人:  zengpan_panpan()   (   )   信誉:100    2004-1-12   21:45:13    得分:0   
         
        基于对象和面向对象的定义也不是我说的,以前是这么定义的。 
        至于JAVA要去掉继承,从方法角度讲是可行,不过至少还得保留接口,否则多态无从谈起。不过这需要推翻整个jdk,肯定就不现实了。另外,看看Object类的实现可以发现,里面的notify,   wait系列方法,有多少时候用到了,要知道任何一个对象都有这样的方法,而这两个方法明显是线程相关的;然而线程类仅仅是它的一个子孙而已。这会让人觉得别扭。其实这个问题的关键在于java不仅仅是一门语言,还是一个运行环境(jvm),它们是紧紧捆绑在一起的,Object如此定义是一个妥协的结果。  
         
        呵呵,扯远了,回到面向对象问题上来: 
        其实,面向对象也好,面向过程也好,现在喊得火热的GP也好,争来争去,没有太大意义。不管什么应用,都是面向需求的,这样那样的方法都是手段而已,目的才是最重要的。理论说多了乏味得很。 
         
        关于面向对象方法,有一个比较经典的例子。我回了最后一篇,不过后来沉下去了。 
         
        欢迎提出不同意见。 
         
        另外,我来出个题目: 
         
        需求很简单:设计个线程池。 
         
        于是现在假设出两种方案,互相对比一下。从需求入手: 
         
        1.   方案一:假设有一线程池对象  tpool;  
            Thread   t   =   tpool.get();  
            t.start(myrunner);  
            tpool.put(t);  
         
        2.   方案二:假设有一线程池类  TPool;  
            TPool.start(myrunner);  
         
        你觉得哪个好,好在哪里,哪个不好,不好又在哪里? 

      zengpan_panpan()   (   )    太精彩了,你的解释,我也随便拜读你的连接文章。:)  果然精彩,请您继续为我们讲解啊。 
         
        我觉得是第二种好。 
        虽然两个都是基于对象的。 
        但是,线程中,反复的创建销毁对象是非常耗资源的。 
        我具体也不怎么会解释,这些池化类方法是比较好的,, 
        让我想到了数据库的连接池。。。。 
         
        请您给我们答案吧。。。期待中。 
         
         
        灯光,,掌声。。。。大家把手机关了:) 
         
        回复人:  zengpan_panpan()   (   )   信誉:100    2004-1-15   14:56:07    得分:0   
         
        其实第一种方法不好。 
        虽然符合一般池子的概念,比如,向池子申请资源,归还资源。 
         
        但是就因为这样将造成线程使用者和线程池之间的强耦合。 
         
        比如向线程池请求一个线程,就不得不考虑,它还有没有线程可以提供给我用?如果没有到底是返回错误,还是还是把我挂起?另外线程运行了我的runner,我什么时候知道知道它结束,如果它还没有结束,我又怎么能把线程归还给池子。考虑这些问题自然就很麻烦了,不但设计应用麻烦,设计线程池也麻烦。 
         
        而第二种就很简单了。 
        把我的runner直接提供给池子,如果它暂时没有线程可用,那么排队就是了。如果不允许排队可以考虑增加一个addTask,提供个参数说明我不排队,要是没有直接报错。更多的通过这个参数甚至可以控制线程优先级一系列的问题,而不需要对池子有多大改动。 
         
        线程池本身,涉及到很多方面的问题,比如操作系统调度之类的问题,里面也会包含一些对象化的思考,这些思考并不在于用什么具体语言去实现。现在给出第二种的最简单实现,可以去分析一下里面到底有多少对象化概念,有什么模式,也可能像这种模式,不过似是而非,但是这些都不重要,并不见得一定要符合什么模式才是对的。前面已经说过,不管面向什么,不管什么方法,最终都是面向需求的。最后应该把你的程序看成一块胶泥,想捏成圆的就圆的,想捏成方的就方的。 
         
        //   TPool.java  
        import   java.lang.*;  
        import   java.util.*;  
        import   java.io.*;  
         
        class   MyRunner   implements   Runnable  
        {  
                        String  name;  
         
                        public   MyRunner(String  x)  
                        {  
                                       name   =   x;  
                        }  
         
                        public  void   run()  
                        {  
                                       System.out.println("My  name   is   "   +   name);  
                                       try   {   Thread.sleep(50);  }   catch   (Exception   e)   {}  
         
                        }  
        }  
         
        public   class   TPool   implements   Runnable 
        {  
                        private  int   id;  
                        private  static   LinkedList   pool   =   new   LinkedList(); 
                        private  TPool   (int   i)   {   id   =   i;   } 
         
                        public  void   run()  
                        {  
                                       for   (;;)  
                                       {  
                                                      Runnable   r;  
                                                      synchronized(pool)  
                                                      {  
                                                                     System.out.println("[Thread   "   +   id   +  "]   Enter   Sleep");  
                                                                     while   (pool.size()   ==   0)  
                                                                      { 
                                                                                     try  
                                                                                     {  
                                                                                                    pool.wait();  
                                                                                     }  catch(InterruptedException   e)  
                                                                                     {  
                                                                                     }  
                                                                      } 
                                                                      r  =   (Runnable)pool.getFirst();  
                                                                     pool.removeFirst();  
                                                                     System.out.println("[Thread   "   +   id   +  "]   Exec   Runner");  
                                                      }  
                                                      r.run();  
                                       }  
                        }  
         
                        static  void   addTask(Runnable   r)  
                        {  
                                       synchronized(pool)  
                                       {  
                                                      pool.add(r);  
                                                      pool.notifyAll();  
                                       }  
                        }  
         
                        static  void   init   (int   size)  
                        {  
                                       for   (int   i   =  0;   i   <   size;   i++)  
                                                      (new   Thread(new   TPool(i))).start();  
                        }  
         
                        static  void   main(String   args[])  
                        {  
                                       TPool.addTask(new  MyRunner("A"));  
                                       TPool.addTask(new  MyRunner("B"));  
                                       TPool.addTask(new  MyRunner("C"));  
                                       TPool.init(3);  
                                       for(;;)  
                                                      try  
                                                      {  
                                                                     Thread.sleep(1000);  
                                                                      int  n   =   (int)(Math.random()   *   5);  
                                                                     System.out.println("\nGenerate   "   +   n   +  "   Tasks\n");  
                                                                     for   (int   i   =   0;   i   <   n;  i++)  
                                                                                     TPool.addTask(new  MyRunner(   (new   Double(Math.random())).toString()  ));  
                                                      }   catch(Exception   e)  
                                                      {  
                                                      }  
                        }  
        }  

      接口(Interface)是用来定义行为的! 
        抽象类(Abstract  Class)是用来实现行为的! 
        具体类()是用来执行行为的! 
         
        这个不错 
        抽象类用来实现公用行为更好一点 
         
        其实除了interface外,还有adapter模式可以参照

      对于接口、抽象类,我的理解是:从类图出发,根据实际情况定义接口或抽象类,接口是定义行为的,任何一个类都可以看作有一个接口,如果需要可以定义接口,否则不需要定义,而抽象类是可以定义和实现行为,但不能执行行为,因为它不能实例化,但可以定义对象,这个对象的行为是抽象类的实现类的实例的行为。

      从设计上说抽象类的好处有二: 
        一、抽象类提供了部分实现,使子类可以重用部分抽象类的代码 
        二、抽象类为其子类提供了共同的接口(注意:这里说我接口与  java   中的  interface   是不同的) 
                也就是别人可以将各个子类的对象当成抽象类的对象使用。 
                 
        我觉得“为了方便扩展”的说法是荒谬的,如果可以实现,为什么要代码写到别的类中去呢? 
        抽象类的关键是抽象方法,而设计抽象方法的原因是在于抽象类自己没有办法实现这个方法, 
        或者说在抽象类这一层,我们不知道如何实现这个方法,只有到了具体类才有办法知道实现。 
        如“动物”这个抽象类,有一个抽象方法“吃”,但是动物这个类是不能实现“吃这个方法的,  
        只有到了“人”这个类,才能有“用手将东西放进嘴里然后吞下去”这样的实现。  
        “动物”这个类的“吃”方法也不可能有默认的实现,因为现实中没有一个纯“动物”的实例, 
        它要么是“人”类的实例,要么是其它“动物”类子类的实例! 
        但我们一旦碰到一个“动物”对象,就可以调用“吃”这个方法, 
        当然我们也要预期不同对象的实现不是一样的 

      interface表述“has   a”关系,用于描述功能  
        是用来说明它的是实现类是“做什么?”的 
        至于“怎么作?”,interface并不进行约束  
         
        而abstract  class表述“is  a”关系,它在描述功能的同时 
        也通过具体实现部分功能的方式,来约束“怎么作?”  
        只有接受了这个约束,才应该去继承它 
        从而可以将“其中被具体实现的部分功能”,在它的子类中得到重用 
         
        实际使用当中,interface与而abstract   class各有优势,  
        需要权衡。 
         
        不过,有时候,两者也可以兼用 
        《effective  java》中提出, 
        可以声明一个interface描述功能,  
        再提供一个该接口的骨架(skeleton)实现(实现该接口的abstract   class)  
        固化对功能实现方式的约束,从而尽可能地实现重用 
         
        于是就有了另一个问题: 
        在使用当中,可能发现这个skeleton实现不能满足现有需求  
        这时可以在原有的interface基础上,派生出另一个skeleton实现  

      抽象类作为超类,可以将子类的公用逻辑用方法实现,而接口只是定义了实现类的规范(其实就是定义了实现类该做什么) 
        因此子类有公用的逻辑部分就在抽象类里实现该方法的细节,子类中有共性但实现细节不同则定义为抽象方法。抽象类只能被一个子类继承,而接口可以被多个实现类实现,所以同意楼上的接口的多态性更好

      接口:  只定义方法名称,没有方法的具体实现。 
         
        抽象类:  只定义方法名称,没有方法的具体实现。    (与   接口   相同) 
                          定义方法名称,并实现这些方法。                (与  类      相同) 
                          以上两者都有。(真正的抽象类大多是这种方式.  可参看API源代码)  
         
        类:定义的方法必须都有实现。

       

      抽象类与接口在设计时各有什么好处?2007-04-13 13:37接口不能执行任何的方法,而抽象类可以。

      类可以执行许多接口,但只有一个父类。 这个也有人说用接口可以实现多重继承。

      接口不是类分级结构的一部分。而没有联系的类可以执行相同的接口。

       

      具体说说:

      接口是对象属性和方法的描述(但不包括他们具体实现),比如Int32类型实现了IConvertible接口,就说明Int32具有 IConvertible接口所描述的ToDouble()方法。但IConvertible并没有给出实现ToDouble()的内容,需要由 Int32类型自己实现。

      接口用于实现多态。比如Int32,Int64和Single类型都实现了IConvertible借口,那么就说明他们一定都具有ToDouble()方法。所以,定义一个变量是IConvertible类型:

      IConvertible c;

      然后,无论是给c赋任何实现IConvertible类型的变量,我都能够保证,c至少有一个ToDouble()方法可用,而不用关心c具体是什么类型的变量。如

      int i = 3; //Int32

      long j = 6L; //Int64

      float k = 4F; //Single

      则

      c = i;

      c.ToDouble();

      c = j;

      c.ToDouble();

      c = k;

      c.ToDouble();

      都不会发生错误。

      实现接口的类可以显式实现该接口的成员。当显式实现某成员时,不能通过类实例访问该成员,而只能通过该接口的实例访问该成员。

      接口的应用大多数是在DesignPattern时才用到。

      抽象类,从多个对象中抽出来的“共性”,而他的后代,既有共性、又有特性。例如:“图形”是抽象的,没有形状,由点线组成;正方形、圆形是他的派生,可以是对象。 

      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.51cto.com/teayear/3188482,作者:跟张哥学编程,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:Shiro过滤器源码

      下一篇:逆向调试入门-设置API函数断点

      相关文章

      2025-05-19 09:04:44

      使用DoubleLinkedList扩展类,允许Add,Remove,Contains

      使用DoubleLinkedList扩展类,允许Add,Remove,Contains

      2025-05-19 09:04:44
      class , list , null , 扩展
      2025-05-14 10:33:25

      超级好用的C++实用库之网络

      在网络相关的项目中,我们经常需要去获取和设置设备的IP地址、子网掩码、网关地址、MAC地址等信息。这些信息一般与操作系统相关,在Windows系统和Linux系统上调用的接口是不一样的。

      2025-05-14 10:33:25
      Linux , 参数 , 地址 , 接口 , 网卡 , 返回值
      2025-05-14 09:51:15

      JAVA 两个类同时实现同一个接口

      在Java中,两个类同时实现同一个接口是非常常见的。接口定义了一组方法,实现接口的类必须提供这些方法的具体实现。

      2025-05-14 09:51:15
      Lambda , 函数 , 实现 , 接口 , 方法 , 表达式
      2025-05-13 09:49:12

      Java学习(动态代理的思想详细分析与案例准备)(1)

      Java学习(动态代理的思想详细分析与案例准备)(1)

      2025-05-13 09:49:12
      java , 代理 , 代码 , 对象 , 接口 , 方法 , 需要
      2025-05-09 09:30:05

      WebAPi接口安全之公钥私钥加密

      WebAPi接口安全之公钥私钥加密

      2025-05-09 09:30:05
      加密 , 参数 , 接口 , 请求 , 重写
      2025-05-09 08:50:35

      springboot实战学习(11)(更新用户基本信息接口主逻辑)

      springboot实战学习(11)(更新用户基本信息接口主逻辑)

      2025-05-09 08:50:35
      接口 , 方法 , 更新 , 用户 , 请求
      2025-05-09 08:50:35

      springboot实战学习(1)(开发模式与环境)

      springboot实战学习(1)(开发模式与环境)

      2025-05-09 08:50:35
      依赖 , 前端 , 后端 , 开发 , 接口 , 数据库 , 文档
      2025-05-08 09:03:29

      装饰者设计模式(一)

      装饰者设计模式(一)

      2025-05-08 09:03:29
      接口 , 目标 , 装饰 , 设计模式 , 返回值
      2025-05-08 09:03:29

      Java序列化有什么作用

      对java对象进行序列化之后,会变成字节码,这样就会比较方便在网络上进行传输,也可以在磁盘上进行存储。

      2025-05-08 09:03:29
      对象 , 序列化 , 接口 , 构造函数
      2025-05-08 09:03:07

      spring AOP 代理模式

      spring AOP 代理模式

      2025-05-08 09:03:07
      代理 , 动态 , 接口 , 模式
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5247973

      查看更多

      最新文章

      超级好用的C++实用库之网络

      2025-05-14 10:33:25

      JAVA 两个类同时实现同一个接口

      2025-05-14 09:51:15

      Java学习(动态代理的思想详细分析与案例准备)(1)

      2025-05-13 09:49:12

      WebAPi接口安全之公钥私钥加密

      2025-05-09 09:30:05

      springboot实战学习(1)(开发模式与环境)

      2025-05-09 08:50:35

      springboot实战学习(11)(更新用户基本信息接口主逻辑)

      2025-05-09 08:50:35

      查看更多

      热门文章

      JAVA__接口的作用

      2023-04-18 14:14:13

      什么是api接口

      2023-03-22 09:03:21

      kotlin匿名内部类与接口实现

      2023-04-18 14:15:13

      Java中创建对象的方式

      2023-02-13 09:25:28

      java之十一 Java GUI

      2024-09-25 10:13:34

      Go 语言入门很简单 -- 13. Go 接口 #私藏项目实操分享#

      2023-04-21 03:11:48

      查看更多

      热门标签

      java Java python 编程开发 代码 开发语言 算法 线程 Python html 数组 C++ 元素 javascript c++
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      windows USB 设备驱动开发-USB复合设备的注册

      Redis实现登录(基于session)

      【动态规划】【滑动窗口】【C++算法】 629K 个逆序对数组

      初始JavaEE篇——多线程(1):Thread类的介绍与使用

      从源码角度学习java函数式编程

      springboot系列教程(二十五):springboot整合ElasticSearch,实现高性能搜索引擎

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号