将 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"

也许不可能重用具有继承类属性的基类方法?

将 Python 移植到 C# 时出现方法继承问题

不需要

在子类中重新定义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"