仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1586|回复: 19
打印 上一主题 下一主题

[学习教程] JAVA编程:为何Java中承继是无害的

[复制链接]
第二个灵魂 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-18 11:44:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
Java到底会发战成什么样,让我们拭目以待吧,我始终坚信着java会更好。以上都是俺个人看法,欢迎大家一起交流.承继概述

  年夜多半好的计划者象回避瘟疫一样来制止利用完成承继(extends干系)。实践上80%的代码应当完整用interfaces写,而不是经由过程extends。“JAVA计划形式”一书具体论述了如何用接口承继取代完成承继。这篇文章形貌计划者为何会这么作。

  Extends是无害的;大概关于CharlesManson这个级其余不是,可是充足糟的它应当在任何大概的时分被避开。“JAVA计划形式”一书花了很年夜的部分会商用interface承继取代完成承继。

  好的计划者在他的代码中,年夜部分用interface,而不是详细的基类。本文会商为何计划者会如许选择,而且也先容一些基于interface的编程基本。

接口(Interface)和类(Class)

  一次,我列入一个Java用户组的集会。在集会中,JamsGosling(Java之父)做倡议人发言。在那使人难忘的Q&A部分,有人问他:“假如你从头机关Java,你想改动甚么?”。“我想丢弃classes”他回覆。在笑声停息后,它注释说,真实的成绩不是因为class自己,而是完成承继(extends干系)。接口承继(implements干系)是更好的。你应当尽量的制止完成承继。

得到了天真性

  为何你应当制止完成承继呢?第一个成绩是明白的利用详细类名将你流动到特定的完成,给底层的改动增添了不用要的坚苦。

  在以后的急迅编程办法中,中心是并行的计划和开辟的观点。在你具体计划程序前,你入手下手编程。这个手艺分歧于传统办法的情势----传统的体例是计划应当在编码入手下手前完成----可是很多乐成的项目已证实你可以更疾速的开辟高质量代码,相对传统的墨守成规的办法。可是在并行开辟的中心是主意天真性。你不能不以某一种体例写你的代码以致于最新发明的需求可以尽量没有疾苦的兼并到已有的代码中。

  胜于完成你大概必要的特性,你只需完成你明白必要的特性,并且过度的对变更的包涵。假如你没有这类天真,并行的开辟,那几乎不成能。

  关于Inteface的编程是天真布局的中心。为了申明为何,让我们看一下当利用它们的时分,会产生甚么。思索上面的代码:

f()
{LinkedListlist=newLinkedList();
//...
g(list);
}

g(LinkedListlist)
{
list.add(...);
g2(list)
}



  如今,假定一个关于疾速查询的需求被提出,以致于这个LinkedList不克不及够办理。你必要用HashSet来取代它。在已有代码中,变更不克不及够部分化,由于你不单单必要修正f()也必要修正g()(它带有LinkedList参数),而且另有g()把列表传送给的任何代码。象上面如许重写代码:

f()
{Collectionlist=newLinkedList();
//...
g(list);
}

g(Collectionlist)
{
list.add(...);
g2(list)
}



  如许修正Linkedlist成hash,大概只是复杂的用newHashSet()取代newLinkedList()。就如许。没有其他的必要修正的中央。

  作为另外一个例子,对照上面两段代码:

f()
{Collectionc=newHashSet();
//...
g(c);
}

g(Collectionc)
{
for(Iteratori=c.iterator();i.hasNext())
do_something_with(i.next());
}





f2()
{Collectionc=newHashSet();
//...
g2(c.iterator());
}

g2(Iteratori)
{while(i.hasNext())
do_something_with(i.next());
}



  g2()办法如今可以遍历Collection的派生,就像你可以从Map中失掉的键值对。现实上,你可以写iterator,它发生数据,取代遍历一个Collection。你可以写iterator,它从测试的框架大概文件中失掉信息。这会有伟大的天真性。

耦合

  关于完成承继,一个加倍关头的成绩是耦合---使人急躁的依附,就是那种程序的一部分关于另外一部分的依附。全局变量供应典范的例子,证实为何强耦合会引发贫苦。比方,假如你改动全局变量的范例,那末一切用到这个变量的函数大概都被影响,以是一切这些代码都要被反省,变动和从头测试。并且,一切用到这个变量的函数经由过程这个变量互相耦合。也就是,假如一个变量值在难以利用的时分被改动,一个函数大概就不准确的影响了另外一个函数的举动。这个成绩明显的埋没于多线程的程序。

  作为一个计划者,你应当勉力最小化耦合干系。你不克不及一并打消耦合,由于从一个类的对象到另外一个类的对象的办法挪用是一个松耦合的情势。你不成能有一个程序,它没有任何的耦合。但是,你可以经由过程恪守OO划定规矩,最小化必定的耦合(最主要的是,一个对象的完成应当完整埋没于利用他的对象)。比方,一个对象的实例变量(不是常量的成员域),应当老是private。我意义是某段时代的,无破例的,不休的。(你可以偶然无效地利用protected办法,可是protected实例变量是可爱的事)一样的缘故原由你应当不必get/set函数---他们关于是一个域公用只是令人感应过于庞大的体例(只管前往润色的对象而不是基础范例值的会见函数是在某些情形下是由缘故原由的,那种情形下,前往的对象类是一个在计划时的关头笼统)。

  这里,我不是墨客气。在我本人的事情中,我发明一个间接的互相干系在我OO办法的严厉之间,疾速代码开辟和简单的代码完成。不管甚么时分我违背中央的OO准绳,照实现埋没,我了局重写谁人代码(一样平常由于代码是不成调试的)。我没偶然间重写代码,以是我遵守那些划定规矩。我体贴的完整有用―我对洁净的缘故原由没有乐趣。

懦弱的基类成绩

  如今,让我们使用耦合的观点到承继。在一个用extends的承继完成体系中,派生类长短常严密的和基类耦合,当且这类严密的毗连是不希冀的。计划者已使用了外号“懦弱的基类成绩”往形貌这个举动。基本类被以为是懦弱的是,由于你在看起来平安的情形下修正基类,可是当从派生类承继时,新的举动大概引发派生类呈现功效杂乱。你不克不及经由过程复杂的在断绝下反省基类的办法来分辩基类的变更是平安的;而是你也必需看(和测试)一切派生类。并且,你必需反省一切的代码,它们也用在基类和派生类对象中,由于这个代码大概被新的举动所冲破。一个关于基本类的复杂变更大概招致全部程序不成操纵。

  让我们一同反省懦弱的基类和基类耦合的成绩。上面的类extends了Java的ArrayList类往使它像一个stack来运转:

classStackextendsArrayList
{privateintstack_pointer=0;

publicvoidpush(Objectarticle)
{add(stack_pointer++,article);
}

publicObjectpop()
{returnremove(--stack_pointer);
}

publicvoidpush_many(Object[]articles)
{for(inti=0;i<articles.length;++i)
push(articles[i]);
}
}



乃至一个象如许复杂的类也有成绩。思索当一个用户均衡承继和用ArrayList的clear()办法往弹出仓库时:

Stacka_stack=newStack();
a_stack.push("1");
a_stack.push("2");
a_stack.clear();



  这个代码乐成编译,可是由于基类不晓得关于stack指针仓库的情形,这个stack对象以后在一个不决义的形态。下一个关于push()挪用把新的项放进索引2的地位。(stack_pointer确当前值),以是stack无效地有三个元素-下边两个是渣滓。(Java的stack类恰是有这个成绩,不要用它).

  对这个使人厌恶的承继的办法成绩的办理举措是为Stack掩盖一切的ArrayList办法,那可以修正数组的形态,以是掩盖准确的操纵Stack指针大概抛出一个破例。(removeRange()办法关于抛出一个破例一个好的候选办法)。

  这个办法有两个弱点。第一,假如你掩盖了一切的工具,这个基类应当真实的是一个interface,而不是一个class。假如你不必任何承继办法,在完成承继中就没有这一点。第二,更主要的是,你不克不及够让一个stack撑持一切的ArrayList办法。比方,使人懊恼的removeRange()没有甚么感化。独一完成无用办法的公道的路子是使它抛出一个破例,由于它应当永久不被挪用。这个办法无效的把编译毛病成为运转毛病。欠好的办法是,假如办法只是不被界说,编译器会输入一个办法未找到的毛病。假如办法存在,可是抛出一个破例,你只要在程序真实的运转时,你才干够发明挪用毛病。

  关于这个基类成绩的一个更好的办理举措是封装数据布局取代用承继。这是新的和改善的Stack的版本:

classStack
{
privateintstack_pointer=0;
privateArrayListthe_data=newArrayList();

publicvoidpush(Objectarticle)
{
the_data.add(stack_poniter++,article);
}

publicObjectpop()
{
returnthe_data.remove(--stack_pointer);
}

publicvoidpush_many(Object[]articles)
{
for(inti=0;i<o.length;++i)
push(articles[i]);
}
}



  到如今为止,一向都不错,可是思索懦弱的基类成绩,我们说你想要在stack创立一个变量,用它在一段周期内跟踪最年夜的仓库尺寸。一个大概的完成大概象上面如许:

classMonitorable_stackextendsStack
{
privateinthigh_water_mark=0;
privateintcurrent_size;

publicvoidpush(Objectarticle)
{
if(++current_size>high_water_mark)
high_water_mark=current_size;
super.push(article);
}

publishObjectpop()
{
--current_size;
returnsuper.pop();
}

publicintmaximum_size_so_far()
{
returnhigh_water_mark;
}
}



  这个新类运转的很好,最少是一段工夫。不幸的是,这个代码开掘了一个现实,push_many()经由过程挪用push()来运转。起首,这个细节看起来不是一个坏的选择。它简化了代码,而且你可以失掉push()的派生类版本,乃至当Monitorable_stack经由过程Stack的参考来会见的时分,以致于high_water_mark可以准确的更新。

注:“JAVA计划形式”
到时我们不用学struts,不用学spring,不用学Hibernate,只要能把jsf学会了,完全可以替代所有的框架,包括AJAX,都知道AJAX并不是新技术,虽说我没深入学习jsf但我认为jsf应该已经能通过其它技术替代AJAX,实现无缝刷新。
若天明 该用户已被删除
沙发
发表于 2015-1-21 13:43:48 | 只看该作者
是一种使网页(Web Page)由静态(Static)转变为动态(Dynamic)的语言
透明 该用户已被删除
板凳
发表于 2015-1-30 19:33:42 | 只看该作者
在全球云计算和移动互联网的产业环境下,Java更具备了显著优势和广阔前景。
只想知道 该用户已被删除
地板
发表于 2015-2-1 18:55:19 | 只看该作者
Java 编程语言的风格十分接近C、C++语言。
5#
发表于 2015-2-7 13:36:58 | 只看该作者
你可以去承接一些项目做了,一开始可能有些困难,可是你有技术积累,又考虑周全,接下项目来可以迅速作完,相信大家以后都会来找你的,所以Money就哗啦啦的。。。。。。
灵魂腐蚀 该用户已被删除
6#
发表于 2015-2-7 13:54:35 | 只看该作者
有时间再研究一下MVC结构(把Model-View-Control分离开的设计思想)
乐观 该用户已被删除
7#
发表于 2015-2-22 03:41:45 | 只看该作者
Java是一种计算机编程语言,拥有跨平台、面向对java
小妖女 该用户已被删除
8#
发表于 2015-2-24 05:52:58 | 只看该作者
是一种为 Internet发展的计算机语言
谁可相欹 该用户已被删除
9#
发表于 2015-2-25 17:24:43 | 只看该作者
是一种使网页(Web Page)产生生动活泼画面的语言
飘灵儿 该用户已被删除
10#
发表于 2015-3-8 00:18:28 | 只看该作者
Java 编程语言的风格十分接近C、C++语言。
金色的骷髅 该用户已被删除
11#
发表于 2015-3-15 17:29:58 | 只看该作者
如果你学过HTML,那么事情要好办的多,如果没有,那你快去补一补HTML基础吧。其实JSP中的Java语法也不多,它更象一个脚本语言,有点象ASP。
第二个灵魂 该用户已被删除
12#
 楼主| 发表于 2015-3-22 02:10:33 | 只看该作者
象、泛型编程的特性,广泛应用于企业级Web应用开发和移动应用开发。
精灵巫婆 该用户已被删除
13#
发表于 2015-3-27 20:11:05 | 只看该作者
吧,现在很流行的Structs就是它的一种实现方式,不过Structs用起来实在是很繁,我们只要学习其精髓即可,我们完全可以设计自己的MVC结构。然后你再研究一下软件Refactoring (重构)和极限XP编程,相信你又会上一个台阶。 做完这些,你不如整理一下你的Java代码,把那些经典的程序和常见的应用整理出来,再精心打造一番,提高其重用性和可扩展性。你再找几个志同道合的朋友成立一个工作室吧
变相怪杰 该用户已被删除
14#
发表于 2015-3-30 10:50:30 | 只看该作者
所以现在应用最广泛又最好学的就是J2EE了。 J2EE又包括许多组件,如Jsp,Servlet,JavaBean,EJB,JDBC,JavaMail等。要学习起来可不是一两天的事。那么又该如何学习J2EE呢?当然Java语法得先看一看的,I/O包,Util包,Lang包你都熟悉了吗?然后再从JSP学起。
深爱那片海 该用户已被删除
15#
发表于 2015-4-7 08:37:14 | 只看该作者
设计模式是高级程序员真正掌握面向对象核心思想的必修课。设计模式并不是一种具体"技术",它讲述的是思想,它不仅仅展示了接口或抽象类在实际案例中的灵活应用和智慧
海妖 该用户已被删除
16#
发表于 2015-5-8 14:17:14 | 只看该作者
那么我书也看了,程序也做了,别人问我的问题我都能解决了,是不是就成为高手了呢?当然没那么简单,这只是万里长征走完了第一步。不信?那你出去接一个项目,你知道怎么下手吗,你知道怎么设计吗,你知道怎么组织人员进行开发吗?你现在脑子里除了一些散乱的代码之外,可能再没有别的东西了吧!
简单生活 该用户已被删除
17#
发表于 2015-5-8 22:17:36 | 只看该作者
是一种使网页(Web Page)产生生动活泼画面的语言
再见西城 该用户已被删除
18#
发表于 2015-6-12 01:29:15 | 只看该作者
Pet Store.(宠物店)是SUN公司为了演示其J2EE编程规范而推出的开放源码的程序,应该很具有权威性,想学J2EE和EJB的朋友不要 错过了。
兰色精灵 该用户已被删除
19#
发表于 2015-6-12 19:16:49 | 只看该作者
让你能够真正掌握接口或抽象类的应用,从而在原来的Java语言基础上跃进一步,更重要的是,设计模式反复向你强调一个宗旨:要让你的程序尽可能的可重用。
愤怒的大鸟 该用户已被删除
20#
发表于 2015-7-7 17:29:12 | 只看该作者
当然你也可以参加一些开源项目,一方面可以提高自己,另一方面也是为中国软件事业做贡献嘛!开发者在互联网上用CVS合作开发,用QQ,MSN,E-mail讨论联系,天南海北的程序员分散在各地却同时开发同一个软件,是不是很有意思呢?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-12-29 08:25

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表