我想将一些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"
也许不可能重用具有继承类属性的基类方法?
答案 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"