说我有一个课程如下
class FootballPlayer
{
public string Name { get; set; }
public string TeamName { get; set; }
public int CareerGoals { get; set; }
public int CareerAssists { get; set; }
public int CareerPasses { get; set; }
public int SeasonGoals { get; set; }
public int SeasonAssists { get; set; }
public int SeasonPasses { get; set; }
public int CurrentMatchGoals { get; set; }
public int CurrentMatchAssists { get; set; }
public int CurrentMatchPasses { get; set; }
}
但我想更好地组织它,所以我该怎么做呢。目前我尝试过这样的事情 -
class CareerDetails
{
public int Goals;
public int Assists;
public int Passes;
}
class CurrentMatchDetails
{
public int Goals;
public int Assists;
public int Passes;
public bool IsCaptain;
}
class GeneralDetails
{
public string Name;
public string TeamName;
}
class SeasonDetails
{
public int Goals;
public int Assists;
public int Passes;
public int MatchesPlayed;
}
class FootballPlayer
{
public CurrentMatchDetails CurrentMatchDetails { get; set; }
public SeasonDetails SeasonDetails { get; set; }
public CareerDetails CareerDetails { get; set; }
public GeneralDetails GeneralDetails { get; set; }
}
我不喜欢的一些事情
但我不确定这是否是最好的做法。我正在考虑在FootballPlayer类中创建一个嵌入式类。
我将在WPF应用程序中使用该类,并在我的INotifyPropertyChanged
类上实现FootballPlayer
。通过使用上面的方法,我将不得不在CareerDetails
等所有类上使用INPC。那么我应该做什么,或者我应该坚持使用我所拥有的?
我可能有另一个名为'FootballTeam'的基类,它也可能有一个名为CurrentMatchDetails的子类 - 它可能看起来像这样
class CurrentMatchDetails
{
public double TimeElapsed;
public string RefereeName;
}
所以我应该能够访问像teamObject.CurrentMatchDetails.RefereeName或playerObject.CurrentMatchDetails.Goals这样的属性;
答案 0 :(得分:8)
您应该创建一个StatDetails
对象:
class FootballPlayer
{
public FootballPlay()
{
CareerStats = new StatDetails();
SeasonStats = new StatDetails();
CurrentStats = new StatDetails();
}
public string Name { get; set; }
public string TeamName { get; set; }
public StatDetails CareerStats { get; set; }
public StatDetails SeasonStats { get; set; }
public StatDetails CurrentStats { get; set; }
}
class StatDetails
{
public int Goals { get; set; }
public int Assists { get; set; }
public int Passes { get; set; }
}
通过这种方式,您只需要在两个类上实现INotifyPropertyChanged
。
答案 1 :(得分:1)
我可能有另一个名为'FootballTeam'的基类,它可以有一个名为CurrentMatchDetails的子类
首先,名为FootBallTeam
的类永远不应该有一个名为CurrentMatchDetails
的子类。继承不是代码共享机制,而是根据物理世界进行建模。 CurrentMatchDetails
是FootballTeam
吗?我看不出来。这种模型的继承工作:
class FootballPlayer
{
}
class StarPlayer : FootballPlayer
{
}
此处StarPlayer
是 FootballPlayer
,所以足球运动员的所有属性也应该在明星球员身上。你应该使用作文,请在这里阅读更多:Prefer composition over inheritance?。在您的情况下,FootBallTeam
应该是CurrentMatchDetails
上的属性。
我没有比Ed更好的答案(给他+1),我会尝试进一步充实他。
public class PlayerStat //Add 'Player' to name since stats can be for tourneys too
{
public int Goals { get; set; }
public int Assists { get; set; }
public int Passes { get; set; }
}
public class PlayerCurrentMatchStat : PlayerStat
{
public bool IsCaptain { get; set; }
}
public class PlayerSeasonStat : PlayerStat
{
public int MatchesPlayed { get; set; }
}
public class PlayerCareerStat : PlayerStat
{
}
//And your football player goes like this:
class FootballPlayer
{
public FootballPlay()
{
CurrentStats = new CurrentStat();
SeasonStats = new SeasonStat();
CareerStats = new CareerStat();
}
public string Name { get; set; }
public string TeamName { get; set; }
public PlayerCurrentMatchStat CurrentMatchStat { get; set; }
public PlayerSeasonStat SeasonStat { get; set; } //no need of naming 'Player'
public PlayerCareerStat CareerStat { get; set; } //inside Player class
}
如果某些类的可见性困扰您,您可以通过将它们推送到某个特定的命名空间来保护它。最后,即使他们不在比赛中,足球队仍然是完全有效的实体。以这种方式建模:
class FootballTeam
{
// all what makes a good unit
}
class FootballMatch
{
public FootBallTeam Team1 { get; set; }
public FootBallTeam Team2 { get; set; }
public double TimeElapsed { get; set; }
public string RefereeName { get; set; }
}
有道理。现在称之为:
FootballMatch currentMatch = new FootballMatch(...whatever
警告:上面的设计还可以,但还是有点臭。为什么FootballPlayer
会有PlayerCurrentMatchStat
?即使他在替补席上,足球运动员仍然是一个完美的球员。如果他不在比赛中,你可能会把它变为空。同样适用于PlayerSeasonStat
- 如果是这样的季节?我会完全重新设计它,而且imo有点复杂,但更合乎逻辑。
public interface Stat //common interface which can be for tourneys, matches etc too
{
int Goals { get; set; }
int Assists { get; set; }
int Passes { get; set; }
}
//You might want to break this interface further to fit in other specific stats
//like player stat, match stat etc.
//Also making it an interface rather than base class is better, you shouldnt have
//2 different entities like PlayerStat and MatchStat share a common base class
public class PlayerStat : Stat //can be career stat, single match stat etc;
{ //depends on context where you call it
public int Goals { get; set; }
public int Assists { get; set; }
public int Passes { get; set; }
}
//another example
public class MatchStat : Stat
{
public int Goals { get; set; }
public int Assists { get; set; }
public int Passes { get; set; }
public int Viewership { get; set; }
}
class Team
{
// all what makes a good unit
}
class Match
{
public Team Team1 { get; set; }
public Team Team2 { get; set; }
public double TimeElapsed { get; set; }
public string RefereeName { get; set; }
public MatchStat Stat { get; set; } //a match has match stat
}
//provide a suitable constructor that takes a player and a match
public class PlayerMatchStat
{
public Player Player { get; set; }
public Match Match { get; set; }
public PlayerStat Stat { get; set; } //should return player's stat for this match
public bool IsCaptain { get; set; }
public int DistanceCompleted { get; set; }
}
//provide a suitable constructor that takes a player and a season
public class PlayerSeasonStat
{
public bool Player { get; set; }
public Season Season { get; set; } //have a season class
public PlayerStat Stat { get; set; } //should return player's stat for this season
public int RedCards { get; set; }
}
//and lastly
class Player
{
public Player()
{
//init work
}
public string Name { get; set; }
public PlayerStat CareerStat { get; set; } //just like match has match stat
public Team[] Teams { get; set; } //Team name shouldn't go within a player
//class, he could be in many teams.
//since player inherently has no match or season, we shall provide methods to query them
public PlayerMatchStat GetMatchStat(Match match)
{
return new PlayerMatchStat(match, this);
}
public PlayerSeasonStat GetSeasonStat(Season season)
{
return new PlayerSeasonStat(season, this);
}
}
这里继承是谨慎使用的(在它保证的地方),并且用于良好效果的是组合。