@@ -43,13 +43,55 @@ func (pe *CallParentMethod) GetValue(ctx data.Context) (data.GetValue, data.Cont
4343 // 获取父类方法
4444 method , has := parentClass .GetMethod (pe .Method )
4545 if ! has {
46- return nil , data .NewErrorThrow (pe .GetFrom (), errors . New ( fmt .Sprintf ("父类 %s 没有方法 %s" , parentClassName , pe .Method ) ))
46+ return nil , data .NewErrorThrow (pe .GetFrom (), fmt .Errorf ("父类 %s 没有方法 %s" , parentClassName , pe .Method ))
4747 }
4848
4949 // 检查方法访问权限
5050 if method .GetModifier () == data .ModifierPrivate {
51- return nil , data .NewErrorThrow (pe .GetFrom (), errors . New ( fmt .Sprintf ("父类方法 %s 是私有的,无法访问" , pe .Method ) ))
51+ return nil , data .NewErrorThrow (pe .GetFrom (), fmt .Errorf ("父类方法 %s 是私有的,无法访问" , pe .Method ))
5252 }
5353
54- return data .NewFuncValue (method ), nil
54+ return & ChangeCtxAndCallFuncValue {ctx : classCtx , fun : method }, nil
55+ }
56+
57+ // ChangeCtxAndCallFuncValue parent::A 后内部再调用 parent::B 上下文没有切换导致死循环
58+ type ChangeCtxAndCallFuncValue struct {
59+ ctx * data.ClassMethodContext
60+ fun data.Method
61+ }
62+
63+ // parentMethodFunc 适配器:将 data.Method 包装为 data.FuncStmt,并在调用时切换到父类上下文
64+ type parentMethodFunc struct {
65+ baseCtx * data.ClassMethodContext
66+ method data.Method
67+ }
68+
69+ func (p * parentMethodFunc ) GetName () string { return p .method .GetName () }
70+ func (p * parentMethodFunc ) GetParams () []data.GetValue { return p .method .GetParams () }
71+ func (p * parentMethodFunc ) GetVariables () []data.Variable { return p .method .GetVariables () }
72+ func (p * parentMethodFunc ) Call (callCtx data.Context ) (data.GetValue , data.Control ) {
73+ // 取父类
74+ if p .baseCtx == nil || p .baseCtx .Class == nil || p .baseCtx .Class .GetExtend () == nil {
75+ return nil , data .NewErrorThrow (nil , errors .New ("当前类没有父类" ))
76+ }
77+
78+ parentName := * p .baseCtx .Class .GetExtend ()
79+ vm := callCtx .GetVM ()
80+ parentClass , acl := vm .GetOrLoadClass (parentName )
81+ if acl != nil {
82+ return nil , acl
83+ }
84+
85+ // 使用调用时创建好的变量上下文(callCtx),但切换到父类的方法上下文,保持同一个对象实例
86+ newCtx := & data.ClassMethodContext {ClassValue : & data.ClassValue {
87+ ObjectValue : p .baseCtx .ObjectValue ,
88+ Class : parentClass ,
89+ Context : callCtx ,
90+ }}
91+
92+ return p .method .Call (newCtx )
93+ }
94+
95+ func (c * ChangeCtxAndCallFuncValue ) GetValue (ctx data.Context ) (data.GetValue , data.Control ) {
96+ return data .NewFuncValue (& parentMethodFunc {baseCtx : c .ctx , method : c .fun }), nil
5597}
0 commit comments