相关疑难解决方法(0)

喜欢构成而不是继承?

为什么喜欢构图而不是继承呢?每种方法都有哪些权衡取舍?什么时候应该选择继承而不是作文?

language-agnostic oop inheritance composition aggregation

1538
推荐指数
23
解决办法
29万
查看次数

继承与构成的区别

组成和继承是一样的吗?如果我想实现组合模式,我该如何在Java中实现?

java oop inheritance composition

187
推荐指数
7
解决办法
21万
查看次数

为什么要使用继承?

我知道之前已经讨论过这个问题,但似乎总是假设继承至少有时候比组合更好.我想挑战这个假设,希望获得一些理解.

我的问题是:既然你可以完成与对象组合东西,你可以用经典的继承和自经典的继承是很经常被滥用[1] ,自对象组合为您提供了灵活地改变委托对象运行时,为什么你会永远使用经典继承?

我可以理解为什么你会推荐Java和C++等语言中的继承,这些语言不能提供方便的委派语法.在这些语言中,只要不明显不正确,就可以使用继承来节省大量的输入.但是像Objective C和Ruby这样的其他语言提供了经典的继承非常方便的委托语法.Go编程语言是我所知道的唯一一种语言,它认为经典继承比它的价值更麻烦,并且仅支持代码重用的委托.

陈述我的问题的另一种方式是:即使您知道经典继承对于实现某个模型不是不正确的,那么这个理由是否足以使用它而不是组合?

[1]许多人使用经典继承来实现多态,而不是让他们的类实现接口.继承的目的是代码重用,而不是多态.此外,有些人使用继承来模拟他们对"is-a"关系的直观理解,这种关系往往是有问题的.

更新

我只想在谈到继承时澄清我的意思:

我在谈论一种继承的类型,即一个类继承自部分或完全实现的基类.我不是在谈论继承纯粹抽象的基类,这与实现接口相同,我记录的并不反对.

更新2

我知道继承是实现C++多态性的唯一方法.在这种情况下,显而易见的是你必须使用它.所以我的问题仅限于Java或Ruby等语言,这些语言提供了实现多态的不同方法(分别是接口和鸭子类型).

java language-agnostic oop inheritance composition

60
推荐指数
6
解决办法
4万
查看次数

面向对象的最佳实践 - 继承v组合v接口

我想问一个关于如何处理简单的面向对象设计问题的问题.我对自己处理这种情况的最佳方法有一些想法,但我有兴趣听听Stack Overflow社区的一些意见.还赞赏相关在线文章的链接.我正在使用C#,但问题不是语言特定的.

假设我写一个视频商店应用程序,其数据库中有一个Person表,其中PersonId,Name,DateOfBirthAddress领域.它还有一个Staff表,其中包含指向a的链接PersonId,以及一个Customer也链接到的表PersonId.

一个简单的面向对象的方法是说Customer"是一个" Person,因此创建类有点像这样:

class Person {
    public int PersonId { get; set; }
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string Address { get; set; }
}

class Customer : Person {
    public int CustomerId { get; set; }
    public DateTime JoinedDate { get; set; }
}

class Staff …
Run Code Online (Sandbox Code Playgroud)

oop inheritance composition

39
推荐指数
5
解决办法
2万
查看次数

我应该使用继承还是组合?

我想简短一点.我建有两间HouseA,说BedRoomStudyRoom,从所谓的基类派生两者Room. BedRoom并且StudyRoom有一个同一个父母叫House.此外,房屋内的任何房间只能通过父母进入任何其他房间.如果BedRoom必须访问任何属性StudyRoom,它必须只通过House(即父),反之亦然.

HouseA ISA House
HouseA HAS BedRoom and StudyRoom.
BedRoom ISA Room
StudyRoom ISA Room
Run Code Online (Sandbox Code Playgroud)

现在的问题:让我们说,我建造另一个家(比方说HouseB),这与上面完全相同,但只有一个改变.我不想要两个单独的房间(即BedRoomStudyRoom),而是一个房间(MasterRoom),这两个房间都有这些设施.为了代码可重用性,我可以想到以下设计选项:

Option-1:
HouseB ISA House
HouseB HAS MasterRoom
MasterRoom ISA Room
Run Code Online (Sandbox Code Playgroud)

在这里,我失去了再利用的属性的能力BedRoomStudyRoom我的创造HouseA.请注意,大多数的属性BedRoom,并StudyRoom需要重新实现MasterRoom无论如何,从而导致代码重复.

Option-2:
HouseB ISA House
HouseB HAS MasterRoom
MasterRoom ISA Room
MasterRoom HAS LogicalBedroom
MasterRoom HAS …
Run Code Online (Sandbox Code Playgroud)

oop perl inheritance composition

15
推荐指数
1
解决办法
1498
查看次数

可以通过组合完全替换继承吗?

这个问题不是 "遗产与构成"之类的问题.

我完全理解继承与组合有什么不同,我知道Liskov替换原理,钻石问题,它们的优点和缺点以及这两个概念似乎都很简单.但到处都有关于继承和构成的问题,我想,也许我误解了这个简单的想法.

让我们关注Go.Go是一种来自谷歌的语言,每个人都很兴奋它没有继承,它没有类,但它有组成,这很酷.对我来说,Go中的组合为您提供与其他语言(C++,Java,...)中的继承完全相同的功能 - 组件方法会自动公开并作为后续结构的方法提供,如下所示:

package main

import (
    "fmt"
)

type Car struct{
    name string
}

func (c *Car) move() bool { 
    return true
} 

type MyCar struct{
    Car   
}

func main() {
    var c MyCar
    fmt.Print(c.move())
}
Run Code Online (Sandbox Code Playgroud)

所以总结一下,组合比继承更好,因为:

  1. 更灵活(允许您在运行时更改组件,因此您可以影响"类"的工作方式.
  2. 没有钻石问题(但钻石问题是可以解决的,所以这不是强大的优势)

如果您考虑Go及其接口(每个对象,具有接口定义的方法,实现此接口隐含),您是否拥有最终解决方案?我们可以说含有一些语法糖的成分可以代替遗传吗?

这种设计符合Liskov替代原则.我是否会遗漏某些内容或继承(从任何语言中获知)与Go中已知的组合(和接口)相比没有优势?

===== edit1 =====

为了澄清,可以Go使用"标准"组合机制,就像这样(这个例子的行为与前一个一样):

package main

import (
    "fmt"
)

type Car struct{
    name string
}

func (c *Car) move() bool { 
    return true …
Run Code Online (Sandbox Code Playgroud)

language-agnostic oop inheritance design-patterns composition

8
推荐指数
1
解决办法
1151
查看次数