英文:
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);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论