2017-04-26 26 views
-4

各スポーツ選手の名前と年齢を取り入れた「スポーツ」抽象クラスの10人の選手の配列のオブジェクトをインスタンス化しようとしています。 「テニス」アスリートのクラスと「ゴルフ」アスリートのクラスがあります。Cで基本クラスと派生クラスを使用して配列内のオブジェクトをインスタンス化する

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] .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(); 
} 

であり、ここで派生テニスクラスです(ゴルフクラスは、変数名にちょうどわずかな変化と同じように構成されている)

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; 
      } 
     } 
+1

「スポーツ」、「ゴルフ」、「テニス」クラスはどのように見えますか? –

+9

これらのクラスに対して 'ToString'を実装します –

+2

「正しく出力されていません」は何も教えてくれません。あなたは何を期待していますか?あなたは何を観察していますか?あなたは、あなたが期待したことが正しいと考えている理由は何ですか? –

答えて

0

私はあなたの質問を正しく理解していれば、彼らはいつもNameとを出力するあなたのクラスのフレンドリーな文字列を出力できるようにしたい、そしてそれぞれのスポーツのために彼らはそのスポーツの特定の特性を出力します。

これは、ToStringプロパティをオーバーライドすることで実行できます。これを基底クラスNameAgeで行い、各クラスごとにbase.ToStringと特定のクラスプロパティを出力することができます。例えば

、基底クラスだろう出力名前と年齢:

abstract class Sport 
{ 
    public override string ToString() 
    { 
     return string.Format("{0} {1}", Name, Age); 
    } 

    // Rest of class code omitted... 

とテニスクラスが出力されますいくつかの他の分野にも:

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... 

次に、あなたの出力は次のようになります。また

enter image description here

、0予告そのインスタンスをインスタンス化するために使用されたコンストラクタでTypeプロパティが設定されていないため、Lisa Townsendの場合は文字列が空です。

+0

はい、これは私があなたに感謝のために探していたものです。 – CoreyC

7

このすべてを修正しましょう。あなたのC#キャリアの中で、良い習慣と実践を学ぶべき時が来ました。

abstract class Sport 

スポーツ?いいえ、このクラスはスポーツを表していません。このクラスはというプレーヤーを表します。スポーツは彼らがプレーするものです。 Mainの地元の「アスリート」という名前は、あなたがここで間違いを犯したことを伝えています。 AthleteまたはPlayerなどと呼んでください。 Playerとしましょう。派生クラスはTennisPlayerGolfPlayerまたはGolferとなる可能性があるためです。

protected string name; 
protected int age; 

なぜ保護されていますか?パブリックゲッターとセッターがこれらをラップしています!

バッキングフィールドを完全に削除します。

public string Name 
{ 
    get 
    { 
     return name; 
    } 
    set 
    { 
     name = value; 
    } 
} 

これらは不必要に言葉遣いです。自動プロパティを使用します。

public int Age 

年齢は常に変化します。誕生日はありません。誕生日を格納し、その後、私はこの手段が、それはおそらく間違っているかわからない

How to calculate an age based on a birthday?

public abstract void Performance(); 

参照してください。抽象メソッドは通常動詞ですが、これは名詞です。これは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; 
    } 
} 

はるかに理解しやすく、分かりやすい。さあ、いくつかのタイプを導きましょう。ここでもプロパティを短くし、ToStringを追加します。

また、Ratingは本当にです。ですか?身長や体重などの物理量にはダブルスを使用します。私はこれがではなく、のdoubleではないと思われます。 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}"; 
    } 
} 

また、はるかに短く読みやすい。今度は、GolfPlayerまたはGolferなどと同じことをします。

+0

[OK]を、私はそれを感謝し、入力プロパティを割り当てるためにコンストラクタに冗長 'this'キーワードを使用しないのはなぜ私は感謝 – CoreyC

+0

を編集するためにそれを使用するためにあなたに感謝?それが必要ではない場合でもベストプラクティスと考えられていますか? –

+1

@ LucaCremonesi:同様に名前が付けられた2つのものがあり、1つがメンバーで、1つがローカルの場合、メンバーであることがメンバーであることを呼び出すことを好む。それは私が愚かな間違いを避けるのに役立ちます。あなたが愚かな間違いをしていない、またはあなたがそれらを作った時に気にしないような人の人なら、それを進めてそれを省略してください。 –

関連する問題