Instantiating objects in an array using base class and derived classes in C#
我试着为10名"运动"抽象类运动员的数组实例化对象,每个运动员都有名字和年龄,然后有两个派生类:"网球"运动员和"高尔夫"运动员。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class Program { static void Main(string[] args) { Sport[] athlete = new Sport[10]; athlete[0] = new Tennis("John Smith", 18,"Tennis", 5.0, 92); athlete[1] = new Tennis("Lisa Townsend", 15,"Tennis"); athlete[2] = new Tennis("Brian Mills", 17,"Tennis", 4.0, 83); athlete[3] = new Golf("Stacey Bell", 16,"Golf", 10, 20); athlete[4] = new Golf("Tom Spehr", 18,"Golf", 9, 12); athlete[5] = new Golf("Sam Calen", 14,"Golf"); athlete[6] = new Tennis("Karen Strong", 17,"Tennis", 3.0, 78); athlete[7] = new Golf("Ken Able", 15,"Golf", 15, 16); athlete[8] = new Tennis("Troy Soni", 18,"Tennis", 4.5, 93); athlete[9] = new Golf("Toni Palmer", 17,"Golf", 8, 22); for (int i = 0; i < 10; i++) { Console.WriteLine("{0}", athlete[i]); } } } |
我正在尝试像这样打印数组,但它输出不正确。另外,当我尝试将数据字段单独打印为
console.writeline("0_1",运动员[I].姓名,运动员[I].年龄)
我可以让它输出每个运动员的姓名和年龄,但如果我尝试添加其他字段,它们将不会输出。我应该将每个数组对象声明为"运动"而不是网球或高尔夫吗?
编辑:
这是体育课
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | abstract class Sport { protected string name; protected int age; public Sport(string name, int age) { Name = name; Age = age; } public string Name { get { return name; } set { name = value; } } public int Age { get { return age; } set { age = value; } } public abstract void Performance(); } |
这里是派生的网球类(高尔夫类的结构与变量名的细微变化相同)
2让我们把这整件事解决。现在是你职业生涯中学习良好习惯和实践的时候了。
2体育运动?不,这个班不代表运动。这个类代表玩家。运动就是他们所玩的。你在你的
1 2 | protected string name; protected int age; |
为什么要保护?你有公众的getter和setter包装这些!
完全消除支持字段。
1 2 3 4 5 6 7 8 9 10 11 | public string Name { get { return name; } set { name = value; } } |
这些是不必要的冗长;使用自动属性。
1 | public int Age |
年龄在不断地变化;生日不一样。存储生日,然后查看
如何根据生日计算年龄?
1 | public abstract void Performance(); |
我不知道这是什么意思,但可能是错的。抽象方法通常是动词,但这是名词。这不是
我们还想说我们玩什么运动。所以我们来做一个类型。把它们放在一起:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | enum Sport { Tennis, Golf } public abstract class Player { // Consider making Name and Birthday get-only as well. // Is there any situation in which they change after construction? // If not, then *don't allow them to change*! public string Name { get; set; } public DateTime Birthday { get; set; } public abstract Sport Sport { get; } public Player(string name, DateTime birthday) { this.Name = name; this.Birthday = birthday; } } |
更短更容易理解。现在我们来推导一些类型。我们将再次缩短属性,并添加ToString。
另外,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public sealed class TennisPlayer : Player { public override Sport Sport => Sport.Tennis; // Again, do these change after construction? If not // then remove the setters. public decimal Rating { get; set; } public int ServeSpeed { get; set; } public TennisPlayer(string name, DateTime birthday, decimal rating, int speed) : base(name, birthday) { this.Rating = rating; this.ServeSpeed = speed; } public override string ToString() { return @"Tennis player: {Name} {Birthday} {Rating} {ServeSpeed}"; } } |
再一次,这么短,这么容易阅读。现在你对
如果我正确理解您的问题,您希望能够为您的类输出一个友好的字符串,在那里它们总是输出
这可以通过覆盖
例如,基类将输出名称和年龄:
1 2 3 4 5 6 7 8 | abstract class Sport { public override string ToString() { return string.Format("{0} {1}", Name, Age); } // Rest of class code omitted... |
网球课还将输出一些其他领域:
1 2 3 4 5 6 7 8 9 | class Tennis : Sport { public override string ToString() { return string.Format("{0} [Sport: {1}] [Rating: {2}] [Serve Speed: {3}]", base.ToString(), Type, Rating, ServeSpeed); } // Rest of class code omitted... |
然后您的输出将如下所示:
另外,请注意,