设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 5336|回复: 15
打印 上一主题 下一主题

[已经解决] 在父类和子类中同时alias同名方法竟然会出错,啥原因

[复制链接]

Lv2.观梦者

旅之愚者

梦石
0
星屑
275
在线时间
812 小时
注册时间
2007-7-28
帖子
2148

贵宾

跳转到指定楼层
1
发表于 2010-7-22 15:07:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

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

x
本帖最后由 六祈 于 2010-7-22 17:53 编辑
  1. class Window_Selectable < Window_Base
  2.   alias old_initialize initialize
  3.   def initialize(x, y, width, height)
  4.     old_initialize(x, y, width, height)
  5.     @last_index = 0
  6.     @disable_items = []
  7.   end
  8.   
  9.   alias old_update_cursor_rect update_cursor_rect
  10.   def update_cursor_rect
  11.     case self.method(:draw_item).arity
  12.     when 2
  13.       draw_item(@last_index,@disable_items.include?(@last_index) ? disabled_color : normal_color)
  14.       draw_item(@index,system_color)
  15.     else
  16.     old_update_cursor_rect
  17.     end
  18.     @last_index = @index
  19.   end
  20. end

  21. class Window_PartyCommand < Window_Selectable
  22.   alias old_update_cursor_rect update_cursor_rect
  23.   def update_cursor_rect
  24.     super()
  25.   end
  26.   alias old_initialize initialize
  27.   def initialize
  28.     old_initialize()
  29.     @disable_items.push 1 unless $game_temp.battle_can_escape
  30.   end
  31. end
复制代码
4行出错,4个实参赋给0个形参

27行的alias后的old_initialize改成别的名字就没问题- -

求真理

Lv3.寻梦者

孤独守望

梦石
0
星屑
3137
在线时间
1535 小时
注册时间
2006-10-16
帖子
4321

开拓者贵宾

2
发表于 2010-7-22 15:17:19 | 只看该作者
我举个例子好了。
A<B<C,A当中有个方法叫a
那么在B类中定义 alias b a
那么C当中还有没有b方法呢?当然有啊。
完毕= =

点评

没看懂例子。。。继承关系似乎反了。。。btw,也就是说window_partycommand里的old_initialize去调用window_selectable里的同名方法了?  发表于 2010-7-22 15:22
菩提本非树,明镜本非台。回头自望路漫漫。不求姻缘,但求再见。
本来无一物,何处惹尘埃。风打浪吹雨不来。荒庭遍野,扶摇难接。
不知道多久更新一次的博客
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
3
发表于 2010-7-22 15:22:46 | 只看该作者
本帖最后由 紫苏 于 2010-7-22 17:05 编辑

4  行 alias 的是 Window_Selectable 的原始 initialize 方法,接着重定义 Window_Selectable#initialize,通过别名 old_initialize 调用原始 initialize 方法;
如果没有在别处定义 Window_PartyCommand#initialize 的话,27 行 alias 的是父类方法 Window_Selectable#initialize,也就是上面刚被重定义的那个 initialize。之后在 Window_PartyCommand 中定义 initialize 方法调用 old_initialize,由于 old_initialize 是顶部被重定义的 Window_Selectable#initialize,并且需要 4 个参数,而 Window_PartyCommand#initialize 调用 old_initialize 时却只传递了 0 个参数,所以会有这个异常。

如果参数列表刚好吻合,就不会有这个异常,但却会产生一个没有出口的递归调用(因为 old_initialize 是 Window_Selectable#initialize 方法本身),最终导致 “Stack level too deep”……

点评

出错信息貌似是4 for 0,在第4行,应该是old_initialize在window_partycommand环境下的调用,传递了4个参数过去,而方法体需要参数为0  发表于 2010-7-22 17:13
懂了,是不是父类重写了方法,子类继承它,那么子类的同名方法也等于被重写了?  发表于 2010-7-22 15:36
回复 支持 反对

使用道具 举报

Lv3.寻梦者

孤独守望

梦石
0
星屑
3137
在线时间
1535 小时
注册时间
2006-10-16
帖子
4321

开拓者贵宾

4
发表于 2010-7-22 15:26:17 | 只看该作者
4  行 alias 的是 Window_Selectable 的原始 initialize 方法,接着重定义 Window_Selectable#initialize, ...
紫苏 发表于 2010-7-22 15:22


于是内建类的悲剧诞生了?那么上次那个反F12是什么原理……(故意歪楼)

评分

参与人数 1星屑 +600 收起 理由
「旅」 + 600 认可答案

查看全部评分

回复 支持 反对

使用道具 举报

Lv2.观梦者

旅之愚者

梦石
0
星屑
275
在线时间
812 小时
注册时间
2007-7-28
帖子
2148

贵宾

5
 楼主| 发表于 2010-7-22 15:33:12 | 只看该作者
回复 紫苏 的帖子
嗯,的确是这样子,不过我还有几个疑惑不太明白

1.为什么打开window_partycommand类的alias会去操作父类呢
2.为什么window_partycommand类中的old_initialize会去调用父类的old_initialize而父类的同名方法却去调用子类的?表示很晕菜啊
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
270 小时
注册时间
2010-2-4
帖子
1305
6
发表于 2010-7-22 15:41:12 | 只看该作者
alias old_initialize initialize相当于定义了父类的old_initialize
父类有了old_initialize就相当于子类有了old_initialize
既然old_initialize为已存在的方法名,自然就无法用来作别的方法的别名了

点评

汗~刚测试了,竟然是4 for 0错误,不过这种诡异的写法倒第一次看到  发表于 2010-7-23 10:03
irb下测试,是可以的  发表于 2010-7-22 15:48
好歹当年也当过大魔王过,orz
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
7
发表于 2010-7-22 15:41:22 | 只看该作者
回复 IamI 的帖子

防 F12 的方式和 C/C++ 避免重复包含头文件的方法基本一致,就是给脚本加个“包含防护罩”:
if(!$__script__built__)
$__script__built__ = 0

# ... 脚本内容 ...

end

话说我咋记得内置的 RGSS 类反而不会有这个问题来着……

点评

F12不刷新内建类 只刷新Ruby内部类  发表于 2010-7-22 15:55
回复 支持 反对

使用道具 举报

Lv2.观梦者

旅之愚者

梦石
0
星屑
275
在线时间
812 小时
注册时间
2007-7-28
帖子
2148

贵宾

8
 楼主| 发表于 2010-7-22 15:47:43 | 只看该作者
回复 紫苏 的帖子
如果没有在别处定义 Window_PartyCommand#initialize 的话,27 行 alias 的是父类方法 Window_Selectable#initialize,也就是上面刚被重定义的那个 initialize。

可是如果27行的别名取做别的就ok了,window_partycommand#initialize也正常(战斗和逃跑指令),愚还是觉得很诡异。。。   


   

点评

取其他别名就不会引起覆盖效应了。重复,alias在整个继承体系中都有效,不能覆盖。  发表于 2010-7-22 15:54
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
9
发表于 2010-7-22 16:09:16 | 只看该作者
回复 六祈 的帖子

27 行取别的名字后,父类的 initialize 里调用的 old_initialize 就仍然是 Window_Selectable 的原始 initialize 方法,而不是子类的 Initialize 了;只有当子类仍然给 initialize 取 old_initialize 这个别名时,父类才会又回去调用子类的 initialize

点评

谢谢紫苏大大,我刚在irb里测试了一下,结果发现alias取的是最高级别的方法,我最后写个总结吧  发表于 2010-7-22 16:17

评分

参与人数 1星屑 +1000 收起 理由
「旅」 + 1000 认可答案

查看全部评分

回复 支持 反对

使用道具 举报

Lv2.观梦者

旅之愚者

梦石
0
星屑
275
在线时间
812 小时
注册时间
2007-7-28
帖子
2148

贵宾

10
 楼主| 发表于 2010-7-22 16:09:50 | 只看该作者
回复 紫苏 的帖子

27行:alias old_initialize initialize
old_initialize如果和父类的同名,那么结果是出错。那么是因为initialize是父类的initialize(因为调用了父类中的old_initialize)?还是者说这个old_initialize仍然去调用父类的这种方法,然后父类的old_initialize又去调用子类的?
而如果改old_initialize的名字的话,那么结果正常。initialize就是子类的了(因为是战斗逃跑菜单,initialize中含有这些信息,如果调用了父类肯定没有这些字了)
   

点评

{:nm_3:}刚刚从magnet和mktorrent里面脱身,结果……你们讨论得好激烈。(算水么?)  发表于 2010-7-22 16:24
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-12-27 06:40

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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