将 Python 移植到 C# 时出现方法继承问题
本文关键字:方法 继承 问题 Python | 更新日期: 2023-09-27 18:30:36
我想将一些Python代码移植到C#。
我目前无法在 C# 中复制以下 Python 代码段。
class X:
a = 'foo'
def x(self):
return self.a;
class Y(X):
a = 'bar'
当我使用我的类时,我得到了所需的行为:
a = X()
b = Y()
a.x() // prints "foo"
b.x() // prints "bar"
但是在 C# 中,我得到了不同的结果。
public class X {
public string a = "foo";
public virtual string xe(){
return this.a;
}
}
public class Y: X{
new public string a = "bar";
}
当我使用我的类时,我得到以下结果:
X a = new X();
Y b = new Y();
a.xe(); // "foo"
b.xe(); // "foo"
也许不可能重用具有继承类属性的基类方法?
不需要
在子类中重新定义a
public class X {
public string a = "foo";
...
}
public class Y: X{
public Y()
{
a = "bar"; // USE THE BASE CLASS [a], AND ASSIGN TO IT DESIRED STRING
}
......
}
等等。正如@ChaosPandition指出的:C#
最佳实践建议不要直接使用公共字段,而是使用属性。并不是说你的代码不起作用,但这不是任何C#
程序员都会编写它的方式。
这
不起作用,因为您的x
方法是在基类型X
中定义的,而不是Y
,因此它只能看到您的A
字符串字段,而不是您的派生字段。
你想要的是一个virtual
属性:
public class X
{
public virtual string A
{
get { return "Foo"; }
}
public virtual string X()
{
return A;
}
}
public class Y : X
{
public override string A
{
get { return "Bar"; }
}
}
类
Y
中的 new
关键字使您仅在 Y
范围内覆盖变量!
引用X.a
时,您只能引用X.a
,而不能引用new Y.a
。不能重写派生类中的变量。
您可以使用属性执行此操作,但如此示例中所示。
public class X {
public virtual string A { get { return "foo"; } }
public virtual x(){
return this.A;
}
}
public class Y: X{
public override string A { get { return "bar"; } }
}
从您的示例中,很难确定具体的用例,如果A
是常量,则可以具有可覆盖的只读属性。
class X
{
public virtual string A { get { return "foo"; } }
}
class Y : X
{
public override string A { get { return "bar"; } }
}
如果它不是常量,而是在创建后不可变,则可以使用构造函数参数。 这个例子是上面更冗长的版本,所以我建议改用它。
class X
{
private readonly string _a;
public X()
{
_a = "foo";
}
protected X(string a)
{
_a = a;
}
public string A { get { return _a; } }
}
class Y
{
public Y() : base("bar")
{
}
}
但是,这两个示例的工作方式相同。
var x = new X();
var y = new Y();
Console.WriteLine(x.A); // foo
Console.WriteLine(y.A); // bar
要在 C# 中完成相同的操作,您需要如下所示的内容:
public class X {
public string a = "foo";
public virtual x(){
return this.a
}
}
public class Y: X{
public Y()
{
a = "bar";
}
}
但是,这并不是真正的 C# 做事方式。一个更好的方法,但要保持你问题的精神,是:
public class X
{
public string a{get;protected set;}
public X()
{
this.a = "foo";
}
public virtual x()
{
return this.a;
}
}
public class Y : A
{
public Y()
{
this.a = "bar";
}
}
不需要
在派生类上重新声明 a。只需在构造函数中将其设置为新值即可。还可以使用属性而不是公共字段。
public class X {
public string {get; set;}
public X() {this.a = "foo";}
public X(string a) {this.a = a;}
}
public class Y: X{
// default constrcutor
public Y() : base() {this.a = "bar";}
public Y(string a) : base(a) {}
}
现在你可以这样做:
X x = new Y("bar");// results in "bar"
X y = new Y(); // also results in "bar"
X y = new Y("test"); // results in "test"
Y y = new Y("test"); // also results in "test"