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

Project1

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

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

[复制链接]

Lv2.观梦者

旅之愚者

梦石
0
星屑
310
在线时间
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改成别的名字就没问题- -

求真理

Lv1.梦旅人

梦石
0
星屑
50
在线时间
462 小时
注册时间
2007-7-30
帖子
643
16
发表于 2010-7-23 08:55:26 | 只看该作者
是3嗎?

点评

yes  发表于 2010-7-23 20:42
回复 支持 反对

使用道具 举报

Lv2.观梦者

旅之愚者

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

贵宾

15
 楼主| 发表于 2010-7-22 17:36:52 | 只看该作者
猜猜看这个结果
  1. class A
  2. def a
  3. b
  4. end
  5. def b
  6. puts 2
  7. end
  8. end
  9. class B < A
  10. def c
  11. puts 3
  12. end
  13. alias b c
  14. end

  15. puts B.new.a
复制代码
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1225
在线时间
1564 小时
注册时间
2008-7-30
帖子
4418

贵宾

14
发表于 2010-7-22 17:33:16 | 只看该作者
本帖最后由 DeathKing 于 2010-7-22 17:42 编辑

回复 DeathKing 的帖子
  1. class A
  2.   def a
  3.     puts 1
  4.   end
  5.   alias :b :a
  6.   undef :a
  7. end

  8. A.new.b
  9. #=> 1
复制代码
才交完水电气回来看到
   




一旦一个类中alias x y了
那么遇到任何调用x的方法,都会去寻找y

如果真这样的话
假设y方法已定义
alias x y
def y
x
end
这样就会死循环了。

点评

自己用就别考虑兼容性,自己重载方法。如果像这样弄得很复杂反而不好维护。  发表于 2010-7-22 17:52
其实我是写了一楼的脚本,出错了,虽然有办法解决,但是搞不懂怎么回事很苦恼。现在总算明白了  发表于 2010-7-22 17:50
真有必要就用模块来Mixin吧……  发表于 2010-7-22 17:49
汗,你觉得这样有必要么?  发表于 2010-7-22 17:48
其实我自己已经明白了。。。你看下15楼,是一个很简化版本的子类调用父类,父类调用方法时使用的是子类的context  发表于 2010-7-22 17:47
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
13
发表于 2010-7-22 17:08:05 | 只看该作者
发现我之前说错了一句话,在原帖编辑了一下,红色部分是修改过的……||||
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1225
在线时间
1564 小时
注册时间
2008-7-30
帖子
4418

贵宾

12
发表于 2010-7-22 16:34:03 | 只看该作者
本帖最后由 DeathKing 于 2010-7-22 16:38 编辑
  1. irb(main):001:0> class A;def a; puts 1;end; alias :c :a;end
  2. => nil
  3. irb(main):002:0> class B<A
  4. irb(main):003:1> def b
  5. irb(main):004:2> puts 2
  6. irb(main):005:2> end
  7. irb(main):006:1> puts respond_to? :c
  8. irb(main):007:1> puts respond_to? :a
  9. irb(main):008:1> end
  10. false
  11. false
  12. => nil
  13. irb(main):009:0> B.superclass
  14. => A
复制代码
不知道是不是因为Ruby 1.9.1的缘故 - -

ri Module#respond_to?

获取帮助(respond_to? 属于元编程(反射机制)的范畴,获取是否可以使用从父类继承的方法。)

我唯一可以说的是,可能Ruby 1.9.1对alias做了手脚,alias方法后,子类就不能使用从父类继承的方法了?但是实例却可以调用?

点评

你这个respond_to?的环境不对,当前self=B(是一个类对象,而c和a都是实例方法)  发表于 2010-7-22 16:45

See FScript Here:https://github.com/DeathKing/fscript
潜心编写URG3中。
所有对URG3的疑问和勘误或者建议,请移步至发布页面。
欢迎萌妹纸催更
回复 支持 反对

使用道具 举报

Lv2.观梦者

旅之愚者

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

贵宾

11
 楼主| 发表于 2010-7-22 16:17:59 | 只看该作者
本帖最后由 六祈 于 2010-7-22 16:56 编辑

回复 六祈 的帖子
真理貌似如下:



一旦一个类中alias x y了
那么遇到任何调用x的方法,都会去寻找y
于是27行后面调用的old_xxx去调用原来的xxx,而原来的xxx含有super去调用父类中的xxx,父类也有alias,xxx去调用old_xxx,然后悲剧发生了,子类在自己的环境中寻找xxx,于是参数异常,如果不异常,则死循环(父子类一直互相调用)

   
谢谢紫苏和IamI两位大人的答疑解惑~bow~
   

点评

应该不能说是调用x会找y吧,而是y中如果有super,alias x y,那么调用x就会找父类的y吧。然后因为y中有x,所以又去找子类的x,结果就参数不符。  发表于 2010-7-23 10:35
如果参数吻合,那父类的 xxx 继续调用 old_xxx,而 old_xxx 正是 xxx 它本身,所以会抛出栈层次太深异常  发表于 2010-7-22 17:12
你这里没有 super 吧,27 行之后 old_xxx 就保存了 xxx 的一份拷贝,调用 old_xxx 就是调用父类的 xxx,父类的 xxx 需要 4 个参数,而你在子类重定义的 initialize 中传递了 0 个,所以有参数异常;如果参数吻合,父   发表于 2010-7-22 17:11
既然你有irb,何妨不跑一下呢?我这里却是2哦~  发表于 2010-7-22 16:26
回复 支持 反对

使用道具 举报

Lv2.观梦者

旅之愚者

梦石
0
星屑
310
在线时间
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中含有这些信息,如果调用了父类肯定没有这些字了)
   
回复 支持 反对

使用道具 举报

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

评分

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

查看全部评分

回复 支持 反对

使用道具 举报

Lv2.观梦者

旅之愚者

梦石
0
星屑
310
在线时间
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也正常(战斗和逃跑指令),愚还是觉得很诡异。。。   


   
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2025-7-14 01:15

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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