【问题标题】:OOP: How would you set up an Artist, Album & Song relationship in OOPOOP:你会如何在 OOP 中建立艺术家、专辑和歌曲的关系
【发布时间】:2011-01-03 01:13:39
【问题描述】:

我了解继承的基础知识,但这一点让我感到困惑。你会怎么说:

  • 专辑对象有一个或多个艺术家对象
  • 专辑对象有一个或多个歌曲对象

我当前的代码只允许每个对象一首歌曲:

class Song extends Album{}
class Album extends Artist{}

我确定我忽略了一些重要的事情。有什么想法吗?

我在 PHP 中这样做

【问题讨论】:

  • 我确定继承不是您要寻找的,而是您所说的关联。
  • 这似乎是一个适合关系数据库答案的问题的教科书示例。歌曲、艺术家和专辑彼此之间都存在多对多的关系。一首歌可以有多个艺术家,并出现在多个专辑中。一张专辑可以有很多艺术家。当然,艺术家和专辑都有很多歌曲。
  • 您对这个项目有什么具体的问题,还是只是想理解“一般”?因为,没有“一般”模型;每个模型都将适合您的特定项目需求。

标签: php oop class inheritance


【解决方案1】:

专辑一个或多个艺术家对象。继承意味着专辑艺术家。你需要的是(编辑)聚合:

class Album
{
  public $artists = array(); // Array of Artist instances
  public $songs   = array(); // Array of Song instances
}

聚合意味着每个 Artist 和 Song 实例都可能属于其他专辑。通过作曲,艺术家或歌曲可能属于一个专辑。

【讨论】:

  • 这个模型并没有真正指出哪些艺术家参与了哪些歌曲。我认为最好有 class Song { string[] artists; string name; int genre }class Album { Song[] songs; string catalog; string publisher } 之类的东西
  • +1,这可能是表达其他几个人(包括我自己)所说的最清晰的方式。
  • 这不是汇总吗?
  • @Gordon :一首歌可能出现在几张专辑中。一位艺术家可以参与多张专辑。我不认为聚合是足够的。
  • @Victor 你的解释正是为什么它应该是一个聚合。专辑不拥有歌曲或艺术家,并且在专辑被销毁时也不会消失。
【解决方案2】:

正如我在我的一个 cmets 中提到的,如果您必须通过 OOP 对其进行建模,我会说,

class Song {
    string[] artists;
    string title;
    int genre;
}

class Album {
    Song[] tracks;
}

【讨论】:

  • +1 我正要写这个。专辑是歌曲的集合,歌曲有标题并由艺术家演唱。
【解决方案3】:

不要为这种关系使用继承,为了所有被油炸和充满美味奶油的东西!

歌曲不是专辑的延伸,它是专辑的一部分。同样,专辑不是艺术家的延伸,它是由艺术家创作的。此外,一首歌可以出现在多张专辑中,一张专辑可以有多个艺术家。

在这种情况下,您应该使用 has-a 关系而不是继承。例如,您可能有一个 Album 对象,其中包含一组 Song 对象作为成员。这将适当地传达歌曲属于专辑的想法。

【讨论】:

    【解决方案4】:

    尝试根据哪些对象具有哪些属性来思考它。 IE。 “汽车一种颜色”或“气球一根绳子”。

    歌曲艺术家

    专辑歌曲

    因此,您的 Song 类将有一个 Artist 对象,而您的 Album 类将包含一组 Song 对象。

    【讨论】:

    • 但是你的陈述不也是正确的吗? Artist **has** Songs,在某种程度上,颜色没有“有”车。在您的模型中,歌曲是否有艺术家,但艺术家没有歌曲?如果我想知道一个艺术家有什么歌曲,我会如何表达?
    • 我没有完全建模整个结构,你说的是真的,Artist has Songs。当您构建模型时,将 Song 对象作为顶级实体可能是最有意义的,并且每首 Song 都会有一个 Album 对象和一个 Artist 对象。在Album has SongsArtist has Songs 的情况下,您将在您的基础歌曲集上执行搜索,以找到适合该艺术家或专辑的曲目。这是否足够体面?
    【解决方案5】:

    我认为这三个类中没有任何继承。歌曲是专辑吗?不,我不认为这样 Song 不应该从 Album 继承。专辑是艺术家吗?不,我也不认为这样,Album 不应该从 Artist 继承。

    相反,您想查看封装。专辑引用零个或多个艺术家。专辑包含零或多首歌曲。一位艺术家引用了零个或多个专辑。

    【讨论】:

      【解决方案6】:

      继承关系被命名为“IS-A”,而您要查找的关系是HAS-A

      你需要这样的东西:

      Album
          artists: Artist[1..*]
          songs  : Song[1..*]
      

      专辑从 1 到多个 (*) 艺术家(由 Artist 数组定义)和 1 张专辑有从 1 到多个 (*) 歌曲,(由 Song 数组定义)

      【讨论】:

        【解决方案7】:

        优先组合而不是继承。

        按照你说的应该是这样的:

        一个专辑对象有一个或多个艺术家对象。一个专辑对象有一个或多个歌曲对象

        类专辑 { 艺术家[] 艺术家; 歌曲[] 歌曲; }

        然而,这并不是我的设想。我认为每张专辑都有一首或多首由一位或多位艺术家演唱的歌曲。我会这样做:

        类专辑 { 歌曲[] 歌曲; // 其他专辑特定属性 }

        类歌曲 { 艺术家[] 艺术家; // 其他歌曲特定属性 }

        类艺术家 { // 艺术家特定属性 }

        我强烈建议您查看 OOD 原则。

        【讨论】:

          【解决方案8】:

          这是我的看法。

          专辑包含歌曲,但歌曲不是专辑。
          专辑与艺术家相关联,但专辑不是艺术家。

          您将继承与关系混合在一起。

          【讨论】:

            【解决方案9】:

            这听起来像是一个数据库建模问题,而不是 OOP 问题。这是因为您很可能拥有一个包含歌曲艺术家和专辑的数据库。不是类层次结构。

            【讨论】:

            • 我不会这么说的。在谈到继承或组合时,数据库没有什么特别的。我认为他只是对 OOP 感到困惑。
            • 非常正确。尤其是因为 ORM 无论如何都会将您的数据转换为对象。
            • 艺术家、歌曲和专辑对象的领域模型是无知的并且与持久层不同,例如:一个数据库。
            【解决方案10】:

            我不确定您是否正确使用了 OOP。通常,当对象具有与父对象相同的功能,但具有一些额外(或特定)功能时,它会扩展父对象。

            以汽车行业为例:

            class Automobile {}
            
            class Truck extends Automobile {}
            class Car extends Automobile {}
            
            class Lexus extends Car{}
            

            看看雷克萨斯是如何最具体的,所以它会随着它的上升而建立一个层次结构?

            你想要的类似于 has_many 关系。一个艺术家有很多专辑,一张专辑有很多歌曲,等等。

            编辑1:正如Victor Nicollet所说,你想要composition

            编辑 2: 如 cmets 所述,您实际上需要 aggregation。提供的文章解释了两者之间的区别。

            【讨论】:

            • 这是聚合,而不是组合。专辑不拥有这些歌曲。
            • 实际上是一个公平的解释。 OP 会知道继承是不相关的,即使这不是他问题的答案。
            • @Gordon - 好点,我有点草率地使用其他词。感谢您指出!
            【解决方案11】:

            如果您让我们知道您希望完成什么,这可能有助于我们得出正确的答案。但是,这些关系通常会存储在您的数据库中。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2014-04-15
              • 2015-03-25
              • 2019-03-16
              • 1970-01-01
              • 1970-01-01
              • 2012-02-15
              • 1970-01-01
              相关资源
              最近更新 更多