使用C#中的基类和派生类在数组中实例化对象

Cor*_*eyC -4 c# arrays abstract

我试图为10名运动员的"运动"抽象课程实例化对象,其中包括每个运动员的名字和年龄,然后有两个派生类别用于"网球"运动员和一个用于"高尔夫"运动员.

  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]);
            }    
        }
    }
Run Code Online (Sandbox Code Playgroud)

我试图像这样打印数组但它输出不正确.当我尝试单独打印数据字段时

Console.WriteLine("{0} {1}",运动员[i] .name,运动员[i] .age)

我可以输出每个运动员的姓名和年龄,但如果我尝试添加其他字段,他们将无法输出.我是否应该将每个数组对象声明为"体育"而不是网球或高尔夫?

编辑:

这是体育课

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();
 }
Run Code Online (Sandbox Code Playgroud)

这里是派生的网球课程(高尔夫课程的结构与变量名称略有不同)

   class Tennis : Sport
    {
        private string type;
        private double rating;
        private int serveSpeed;

        public Tennis(string name, int age, string type, double rating, int serveSpeed) : base(name, age)
        {
            Rating = rating;
            Type = type;
            ServeSpeed = serveSpeed;
        }
        public Tennis(string name, int age, string type) : base(name, age)
        {
        }
        public double Rating
        {
            get
            {
                return rating;
            }
            set
            {
                rating = value;
            }
        }
        public string Type
        {
            get
            {
                return type;
            }
            set
            {
                type = "Tennis";
            }
        }
        public int ServeSpeed
        {
            get
            {
                return serveSpeed;
            }
            set
            {
                serveSpeed = value;
            }
        }
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 8

让我们解决这个问题.现在是您在C#职业生涯中学习良好习惯和习惯的时候了.

abstract class Sport
Run Code Online (Sandbox Code Playgroud)

运动?不.本课程不代表体育.这个班级代表球员.体育是他们的运动.你在当地命名当地"运动员"这一事实Main告诉你,你在这里犯了一个错误.调用此AthletePlayer什么的.让我们说Player,因为那时派生类可以是TennisPlayerGolfPlayerGolfer.

protected string name;
protected int age;
Run Code Online (Sandbox Code Playgroud)

为什么保护?你有公共吸气剂和二传手包装这些!

完全消除支持字段.

public string Name
{
    get
    {
        return name;
    }
    set
    {
        name = value;
    }
}
Run Code Online (Sandbox Code Playgroud)

这些都是不必要的罗嗦; 使用自动属性.

public int Age
Run Code Online (Sandbox Code Playgroud)

年龄不断变化; 生日不.存放生日,然后看

如何根据生日计算年龄?

public abstract void Performance();
Run Code Online (Sandbox Code Playgroud)

我不知道这意味着什么,但可能是错的.抽象方法通常是动词,但这是一个名词.不应该这样Perform吗?还是Play?你从派生类中省略了它,所以让我们忽略它.

我们还想说出我们玩的运动.所以让我们为此做一个类型.把它们放在一起:

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

更短更容易理解.现在让我们推导出一些类型.我们将再次缩短属性,并添加ToString.

还有,Rating真的是双倍的吗?使用双打作为身高,如身高或体重.我怀疑这是小数,而不是双倍.如果将3.4的等级实际存储为3.39999999999999999绝对非常错误,那么double是要使用的错误类型,decimal是要使用的正确类型.

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}";
  }
}
Run Code Online (Sandbox Code Playgroud)

再次,这么短,更容易阅读.现在你做同样的事情,GolfPlayer或者Golfer或者无论你怎么称呼它.