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

时间:2014-11-17 14:36:45

标签: c# .net inheritance

我想将一些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"

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

6 个答案:

答案 0 :(得分:7)

您不需要在子课程中重新定义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#程序员编写它的方式。

答案 1 :(得分:3)

班级new中的Y关键字会覆盖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"; } }
}

答案 2 :(得分:3)

这不起作用,因为您的基本类型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"; }
    }
}

答案 3 :(得分:1)

从您的示例中,很难确定具体的用例,如果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

答案 4 :(得分:0)

要在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";
  }
}

答案 5 :(得分:-1)

您无需在派生类上重新声明。只需在构造函数中将其设置为新值即可。也使用属性而不是公共字段。

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"