在D中调用子类中重载的父类方法

huangapple go评论50阅读模式
英文:

Calling overloaded parent methods from child class in D

问题

假设我有以下的 D 代码:

类 父类 {
    void 打印(int x) {
        导入 std.stdio : writeln;
        writeln(x);
    }

    抽象 void 打印(string s);
}

类 子类 : 父类 {
    重写 void 打印(string s) {
        导入 std.stdio : writeln;
        writeln(s);
    }
}

单元测试 {
    子类 c = 新 子类();
    c.打印(5);
}

当我编译这段代码时,我收到一个编译器错误,指出

函数 子类.打印(string s) 无法使用参数类型 (int) 进行调用

这让我感到困惑,因为我期望调用子类时会调用父类的 打印(int x) 方法。我可以通过内联转换解决这个问题,比如 (cast(父类)c).打印(5),但这看起来很别扭。

这是语言的一个错误吗?还是有更好的继承和重载方法的方法?

英文:

Suppose I have the following D code:

class Parent {
    void print(int x) {
        import std.stdio : writeln;
        writeln(x);
    }

    abstract void print(string s);
}

class Child : Parent {
    override void print(string s) {
        import std.stdio : writeln;
        writeln(s);
    }
}

unittest {
    Child c = new Child();
    c.print(5);
}

When I compile this code, I get a compiler error stating that

function Child.print(string s) is not callable using argument types (int)

This is confusing, because I would expect that the parent's print(int x) method would be invoked when calling it on the child. I can solve this casting inline, like (cast(Parent)c).print(5), but this seems awkward.

Is this a bug in the language? Or is there a better approach to inheritance with overloaded methods?

答案1

得分: 3

你需要修改 Child 类并使用别名来引用 Parent.print:

class Child : Parent {
  
    alias print = Parent.print;

    override void print(string s) {
        import std.stdio : writeln;
        writeln(s);
    }
}

这是故意的,目的是防止函数劫持。您可以在以下链接中了解更多信息:
https://dlang.org/articles/hijack.html

从部分'派生类成员函数劫持'中提取的相关文本:

> C++ 在这方面有正确的思路,即派生类中的函数会隐藏基类中同名的所有函数,即使基类中的函数可能更匹配。D 也遵循这一规则。如果用户希望它们相互重载,可以在 C++ 中使用 using 声明,在 D 中使用类似的 alias 声明来实现。

英文:

You'll need to modify Child with an alias to Parent.print:

class Child : Parent {
  
    alias print = Parent.print;

    override void print(string s) {
        import std.stdio : writeln;
        writeln(s);
    }
}

This is intentional. It's to prevent function hijacking. You can read about it here:
https://dlang.org/articles/hijack.html

The relevant text from the section 'Derived Class Member Function Hijacking':

> C++ has the right idea here in that functions in a derived class hide
> all the functions of the same name in a base class, even if the
> functions in the base class might be a better match. D follows this
> rule. And once again, if the user desires them to be overloaded
> against each other, this can be accomplished in C++ with a using
> declaration, and in D with an analogous alias declaration.

答案2

得分: 1

"问题"出在重载...

以下代码将起作用,因为它避免了对 "print" 方法的重载:

class Parent {
    void printInt(int x) {
        import std.stdio : writeln;
        writeln(x);
    }

    abstract void printString(string s);
}

class Child : Parent {   
    override void printString(string s) {
        import std.stdio : writeln;
        writeln(s);
    }
}

void main() {
    Child c = new Child();
    c.printInt(5);
}

如果你确实想要重载 print() 方法,那么你应该在 Child 类中添加类似 override void print(int x) { super.print(x); } 的内容:

class Parent {
    void print(int x) {
        import std.stdio : writeln;
        writeln(x);
    }

    abstract void print(string s);
}

class Child : Parent {
    override void print(int x) { super.print(x); }

    override void print(string s) {
        import std.stdio : writeln;
        writeln(s);
    }
}

void main() {
    Child c = new Child();
    c.print(5);
}
英文:

"Problem" is in the overloading...

The following code will work because it avoids overloading of the "print" method:

class Parent {
    void printInt(int x) {
        import std.stdio : writeln;
        writeln(x);
    }

    abstract void printString(string s);
}

class Child : Parent {   
    override void printString(string s) {
        import std.stdio : writeln;
        writeln(s);
    }
}

void main() {
    Child c = new Child();
    c.printInt(5);
}

If you really do want to overload the print() method, then you should have something like override void print(int x) { super.print(x); } in your Child:

class Parent {
    void print(int x) {
        import std.stdio : writeln;
        writeln(x);
    }

    abstract void print(string s);
}

class Child : Parent {
    override void print(int x) { super.print(x); }

    override void print(string s) {
        import std.stdio : writeln;
        writeln(s);
    }
}

void main() {
    Child c = new Child();
    c.print(5);
}

huangapple
  • 本文由 发表于 2023年5月11日 16:51:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76225781.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定