第226章
- 作者:吴强
- 类型:综合其他
- 更新时间:2021-07-05 15:14:20
- 章节字数:6484字
大B:“静态分派,动态分派,多分派,单分派是visitor模式准备。”
小A:“visitor模式准备?能不能详细讲讲,我不明白。”
大B:“可以。”
1、静态分派:
(1)定义:发生在编译时期,分派根据静态类型信息发生,重载就是静态分派。
(2)什么是静态类型:变量被声明时的类型是静态类型。
什么是动态类型:变量所引用的对象的真实类型。
(3)有两个类,BlackCat,WhiteCat都继承自。
如下调用
classCat{}
classWhiteCatextendsCat{}
classBlackCatextendsCat{}
publicclassPerson{
publicvoidfeed(Catcat){
(“feedcat”);
publicvoidfeed(WhiteCatcat){
(“feedWhiteCat”);
publicvoidfeed(BlackCatcat){
(“feedBlackCat”);
publicstaticvoidmain(Stringargs){
Catwc=newWhiteCat;
Catbc=newBlackCat;
Personp=newPerson;
www.youxs.org(wc);
www.youxs.org(bc);
运行结果是:
feedcat
feedcat
这样的结果是因为重载是静态分派,在编译器执行的,取决于变量的声明类型,因为wc,bc都是Cat所以调用的都是feed(Catcat)的函数。
2、动态分派
定义:发生在运行期,动态分派,动态的置换掉某个方法。
还是上面类似的例子:
classCat{
publicvoideat{
(“cateat”);
publicclassBlackCatextendsCat{
publicvoideat{
(“blackcateat”);
publicstaticvoidmain(Stringargs){
Catcat=newBlackCat;
www.youxs.org;
}这个时候的结果是:
blackcateat
这样的结果是因为在执行期发生了向下转型,就是动态分派了。
3、单分派:
定义:根据一个宗量的类型进行方法的选择。
4、多分派:
(1)定义:根据多于一个宗量的类型对方法的选择。
(2)说明:多分派其实是一系列的单分派组成的,区别的地方就是这些但分派不能分割。
(3)Java是动态单分派,静态多分派语言。
大B:“访问同一类型的集合类是我们最常见的事情了,我们工作中这样的代码太常见了。”
Iteratorie=;
while(www.youxs.org){
Person
p=(Person)www.youxs.org;
www.youxs.org;
这种访问的特点是集合类中的对象是同一类对象Person,他们拥有功能的方法run,我们调用的恰好是这个共同的方法。在大部份的情况下,这个是可以的,但在一些复杂的情况,如被访问者的继承结构复杂,被访问者的并不是同一类对象,也就是说不是继承自同一个根类。方法名也并不相同。例如JavaGUI中的事件就是一个例子。
例如这样的问题,有如下类和方法:
类:PA,方法:runPA;
类:PB,方法:runPB;
类:PC,方法:runPC;
类:PD,方法:runPD;
类:PE,方法:runPE;
有一个集合类。
Listlist=newArrayList;
(newPA);
(newPB);
(newPC);
(newPD);
(newPE);
……
大B:“要求能访问到每个类的对应的方法。我们第一反应应该是这样的。”
Iteratorie=;
while(www.youxs.org){
Objectobj=www.youxs.org;
if(objinstanceofPA){
((PA)obj).runPA;
}elseif(objinstanceofPB){
((PB)obj).runPB;
}elseif(objinstanceofPC){
((PC)obj).runPC;
}elseif(objinstanceofPD){
((PD)obj).runPD;
}elseif(objinstanceofPE){
((PE)obj).runPE;
大B:“当数目变多的时候,维护ifelse是个费力气的事情:仔细分析if,else做的工作,首先判断类型,然后根据类型执行相应的函数。”
小A:“如何才能解决这两个问题呢?”
大B:“首先想到的是Java的多态,多态就是根据参数执行相应的内容,能很容易的解决第二个问题,我们可以写这样一个类。”
publicclassvisitor{
publicvoidrun(PApa){
www.youxs.org;
publicvoidrun(PBpb){
www.youxs.org;
publicvoidrun(PCpc){
www.youxs.org;
publicvoidrun(PDpd){
www.youxs.org;
publicvoidrun(PEpe){
www.youxs.org;
大B:“这样只要调用run方法,传入对应的参数就能执行了。”
小A:“还有一个问题就是判断类型。”
大B:“由于重载(overloading)是静态多分配。Java语言本身是支持‘静态多分配’的。所以造成重载只根据传入对象的定义类型,而不是实际的类型,所以必须在传入前就确定类型,这可是个难的问题,因为在容器中对象全是Object,出来后要是判断是什么类型必须用if(xxinstanceofxxx)这种方法。”
小A:“如果用这种方法岂不是又回到了原点,有没有什么更好的办法呢?我们知道Java还有另外一个特点,覆写(overriding),而覆写是‘动态单分配’的,那如何利用这个来实现呢?”
大B:“看下边这个方法:我们让上边的一些类PA、PB、PC、PD、PE都实现一个接口P,加入一个方法,accept。”
publicvoidaccept(visitorv){
//把自己传入。
www.youxs.org(this);
然後在visitor中加入一个方法
publicvoidrun(Pp){
//把自己传入。
www.youxs.org(this);
//这样你在遍历中可以这样写
Visitorv=newVisitor;
Iteratorie=;
while(www.youxs.org){
Pp=(P)www.youxs.org;
www.youxs.org(v);
大B:“首先执行的是‘把自己传入2’,在这里由于Java的特性,实际执行的是子类的accept,也就是实际类的accept然后是‘把自己传入1’,在这里再次把this传入,就明确类型,OK我们巧妙的利用overriding解决了这个问题。其实归纳一下第二部分,一个关键点是‘自己认识自己’,是不是很可笑。”
其他好看的小说:
【我的奇葩老妈】【少爷饶了我】【神王令】【提瓦特之我在至冬做卧底】【重生后才发现我有青梅】【人在创骑:开局奈克斯特形态】【谍影:命令与征服】【长生;把寿命卖给魔头,我无敌了】【原神:直播问答,开局应急食品!】【网王立海大的那些事儿】【红星物流从亮剑开始】【年代文悲惨原配要离婚[八零]】【走进不科学】【欧颜】【仙笼】【穿越暗黑之路】【战锤:我在神明的注视下整活】【LOL:我在德玛西亚当摆烂皇子】【四合院:定下十门亲,开局被悔婚】【穿成炮灰男配后我暴富了】【高武:登录未来一万年】【全服首杀】【高武:我的普攻能触发斩杀】【后浪】【从生产队赶大车开始】【正阳门下:开局拿下苏萌!】【全民领主:我掀起植物异化狂潮】【同时谈了八个触手男友】【知否笑长歌】【斗破苍穹之破轮回,炎鳞缘劫】