SuperCollider继承场景下init方法重复调用的问题求助
问题原因
问题出在父类MooPlayer的*new方法上——它在创建实例后直接调用了无参的init(),而子类MooRoot的*new又额外调用了带参的init(moo, name),导致init被执行两次。
当你调用MooRoot(1, "Jessie")时,实际执行流程是:
- 进入
MooRoot的*new方法,打印MooRoot new Jessie - 调用
super.new触发MooPlayer的*new方法 MooPlayer的*new调用super.new.init(),此时因为实例是MooRoot类型,会调用MooRoot的init但不传参数,打印MooRoot init nil- 回到
MooRoot的*new,再次调用.init(moo, name),触发带正确参数的init,打印MooRoot init Jessie - 返回最终实例
解决方案
有两种常用的修正方式:
方案一:父类*new不主动调用init,由子类控制初始化
修改MooPlayer的*new方法,只返回未初始化的实例,把初始化操作完全交给子类:
MooPlayer { var contents, ownedObjects, <>user, <me, <permissions; *new { // 仅返回实例,不调用init ^super.new; } init { } }
此时调用MooRoot(1, "Jessie")的输出会变为:
MooRoot new Jessie MooRoot init Jessie -> a MooRoot
方案二:统一参数传递逻辑,让父类*new支持转发初始化参数
如果父类也需要处理初始化参数,可以调整*new的参数传递逻辑,确保只触发一次init:
MooPlayer { var contents, ownedObjects, <>user, <me, <permissions; *new { |...args| // 将所有参数转发给init方法 ^super.new.init(*args); } init { // 父类可在此处理自身需要的参数,当前为空实现 } } MooRoot : MooPlayer { var <api, <moo; *new { |moo, name| "MooRoot new %".format(name).postln; // 调用父类*new,由父类负责传递参数给init ^super.new(moo, name); } init {|imoo, name| super.init(imoo, name); // 若父类init有逻辑,可传递参数 "MooRoot init %".format(name).postln; } }
这种方式同样能保证init仅被调用一次,输出符合预期。
内容的提问来源于stack exchange,提问作者les_h
相关产品推荐
相关产品推荐

