You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SuperCollider继承场景下init方法重复调用的问题求助

问题原因

问题出在父类MooPlayer的*new方法上——它在创建实例后直接调用了无参的init(),而子类MooRoot的*new又额外调用了带参的init(moo, name),导致init被执行两次。

当你调用MooRoot(1, "Jessie")时,实际执行流程是:

  1. 进入MooRoot的*new方法,打印MooRoot new Jessie
  2. 调用super.new触发MooPlayer的*new方法
  3. MooPlayer的*new调用super.new.init(),此时因为实例是MooRoot类型,会调用MooRoot的init但不传参数,打印MooRoot init nil
  4. 回到MooRoot的*new,再次调用.init(moo, name),触发带正确参数的init,打印MooRoot init Jessie
  5. 返回最终实例
解决方案

有两种常用的修正方式:

方案一:父类*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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 03:05:05