2017-04-26 5 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) 개별적으로 데이터 필드를 인쇄하려고하면 또한

나는 그것을 얻을 수 있습니다 각 선수의 이름과 나이를 출력하지만 다른 필드를 추가하려고하면 출력되지 않습니다. 테니스 또는 골프보다는 각 배열 객체를 "스포츠"로 선언해야합니까?

편집 : 여기

파생 테니스 클래스

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; 
      } 
     } 
(골프 클래스는 같은 방법으로 변수 이름에 단지 약간의 변화 구성되어)있는 스포츠 클래스 여기

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

하고있다

+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 getters와 setters를 이것들로 묶습니다!

뒷받침 필드를 완전히 제거하십시오.

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

감사합니다. 입력 해 주셔서 감사합니다. 고맙습니다. 편집을 위해 사용하겠습니다. – CoreyC

+0

생성자에서 중복 키워드'this'를 사용하여 속성을 할당하는 이유는 무엇입니까? 그것이 필요하지 않은 경우에도 모범 사례로 간주됩니까? –

+1

@ 루카 크레 네네시 (LuchaCremonesi) : 비슷한 이름을 가진 두 가지가 있고 하나는 회원이고 하나는 지역인데, 회원 인 것은 구성원이라는 것을 선호합니다. 어리석은 실수를 피하는 데 도움이됩니다. 어리석은 실수를하지 않거나 만들 때 신경 쓰지 않는 그런 종류의 사람이라면 계속해서 생략하십시오. –