我正在尝试理解面向对象。我当然理解它,但有时候我并不是100%清楚。你如何决定什么应该变成一个对象(另一个大整个对象的小对象部分)或者什么不值得成为一个对象,或者它应该只是那个大整个对象的属性?
对于一扇门,我猜门把手应该是一个独立的物体,但是你插入钥匙的中间部分应该是一个独立的物体还是什么?这是一个简单的例子,所以我可以解释我的困惑。您可以使用您的示例,如果它可以帮助您更好地表达您的观点。
我在想,如果我要多次使用它,我应该把它作为一个对象。我认为这是解决这个问题的实用方法,你同意吗?
由于
答案 0 :(得分:30)
一如既往,答案是不幸的:这取决于......
一开始,你有某种环境,你想为它创建一个模型。但你不会模仿每一件事,你会专注于重要的事情。这就是我开始的原因:这取决于。这取决于完成任务所需的详细信息。
驾驶汽车及其轮子 - 如果您为城市建模并想要一些交通,您可以创建一个属性为'numberOfWheels'的'Car'类。但如果你设计汽车,那么你很可能想要创建一个“轮”类,并将其中的四个添加到'汽车'类。
拇指规则:
修改强>
因为你强调了“多用途”方面:我不认为这是决定是否使用课程的一个方面。想想一个简单的计数器,一个for循环中的整数值。你会使用这个概念数百次,但我敢打赌,你永远不会想到将这个可怜的小int
包装成'计数器'类 - 只是因为你多次使用'计数器的概念'。
答案 1 :(得分:12)
首先:忘记物理对象。我知道所有的教科书“学习示例”都使用它们,但是当你试图模拟一个真实的系统时,你只会迷惑自己。物理对象和对象之间没有直接关系。
对象是一种数据结构,它与一组可以对该数据结构进行操作的方法相结合。对象的属性保持对象状态,方法对状态进行操作。
您尝试建模的系统状态是什么?那是否存在于门,旋钮或两者的某种组合中?
有些方法试图在编码开始之前明确指定对象模型。其他方法(例如,TDD)允许对象模型通过编码过程出现。在您的情况下,我建议使用TDD编写一些中小型应用程序,以便您可以看到各种模式的优缺点。很少有一种“正确”的方式来模拟给定的情况,但有些模型比其他模型更容易使用和理解;认识到适用于你面前情况的模式需要经验。
所以,底线:制作很多模特。考虑应用程序域,对它们进行建模和编码。这样做会使事情变得更加清晰。制作一个沙盒,然后跳进去。
答案 2 :(得分:10)
在决定某件事物是否是某个物体时,请问自己是否有以下物品......
<强>国家强>
候选人是否有重要的州?如果没有,那么它上面的所有方法都可能只是微弱相关。在这种情况下,您可能已经确定了一个可重用函数模块库。
<强>行为强>
对象实际上是否在域中执行某些操作?例如,它只是充满了操纵结构或记录的访问器。
<强>身份强>
对象是否真的存在于域中作为可识别的实体?该实体是否存在一些天生的方面,使其与其他类似的实体区别开来?门把手就是一个例子 - 因为一个门把手可能与另一个门把手相同,所以它并没有真正的标识。
如果你对其中一些回答“否”,那么你可能没有一个对象 - 那么库或模块可以是一个有价值的可重用工件
最重要的是,不要担心......
我也不会过分担心这种重用问题。设计类层次结构就像设计可扩展的软件一样 - 早期优化太容易了。在一张纸上画出一个设计,如果可以的话,用一些手绘交互图验证设计。您会发现,随着时间的推移,您将真正了解真正有价值和可重复使用的内容。
答案 3 :(得分:4)
这取决于使用情况。举个例子,如果门把手是一个重要的部件并且可能(可能)用在另一扇门上(或者用于'这个'的另一个旋钮)那么它应该是一个物体。
另一方面,如果只允许您打开和关闭门,它应该只是门对象的一部分。
答案 4 :(得分:3)
正如古老的陈词滥调所说的“物体应该是名词”。每当你发现自己想到的东西时,它应该是一个对象。每当你发现自己想要一个动作时,它应该是一个功能或方法。
当然,上述规则也有例外,现实可能会更复杂一些。然而,这可能是开始围绕这个概念的最佳起点。
答案 5 :(得分:2)
决定对象粒度的教科书方式是凝聚力。
如果对象的大部分方法都在对象的大部分字段上运行,那么对象就足够小(对于给定的“最”值)。
对象几乎不会太小。
答案 6 :(得分:2)
我建议你考虑一下如何使用它。想一想你将对“事物”做什么操作,然后考虑最简单的方法。有时将其作为另一个对象的属性会更容易,有时将它变成自己的新对象会更容易。
没有通用的配方,可以有许多因素使一种解决方案更好。只需分别考虑每个案例。
已添加:举一个关于门/门把手/钥匙孔的例子 - 您将如何处理钥匙孔?以下是使锁孔成为单独对象的逻辑因素:
将其作为财产的方案恰恰相反:
答案 7 :(得分:2)
如果您需要将其视为......一个对象,那么这是一个对象。
也就是说,如果你需要一个抽象。
您的示例中的“关键孔”可以在不同的抽象层次上描述,只有列表中的最后一个可能称为“对象”:
1)可能是boolean
财产,如果你只是需要知道你的门有它:
class Door
{
bool HasKeyHole;
}
2)可能是一对坐标,如果你只想画门并用一个圆圈代替钥匙孔
class Door
{
Point KeyHoleCoordinates;
}
3)如果你想封装一个关键洞的逻辑和一些属性并与它们一起工作,可能是一个特殊定义的类KeyHole
,可能会传递它们,或允许与Key
交互
class KeyHole
{
Point Coordinates;
bool OpensWithKey(Key key);
}
class Door
{
KeyHole Hole;
}
答案 8 :(得分:1)
的所有内容 可以成为一个对象。
IMO,您问题的答案就是问题 - 我的门模型所需的钥匙孔行为是否准确无误?
如果上述答案是肯定的,请继续并加入。当对同一个问题的回答是否定的时候,我就选择不这样做。
答案 9 :(得分:1)
好老Plato已经有了答案(有点)......
但你的问题在很大程度上取决于你所使用的语言,所以这里没有普遍的真理。在某些语言中, thing 应该是一个类,但它可能是其他对象,或者两者(在具有元对象协议的对象中),或者只是值和相关函数的记录。
答案 10 :(得分:1)
我已经在another question
中回答了这个问题代码对象不与有形现实生活对象相关;它们只是将相关信息保存在一起的结构。
不要相信Java书籍/学校教的对象;他们在说谎。
只要写下完成工作的东西,即使它很难看,然后不断重构:
可是:
如果你没有最终的大规模(和无用的)类层次结构,那么你已经做得很好,生成优雅和干净的代码。
请记住:OOP是一种手段,而不是目的。
答案 11 :(得分:1)
有理论,然后有实践......然后你作为软件工程师试图平衡它们。
理论上你应该把对象做成几乎所有的东西,直到你沦为最小的元素,原始类型(布尔,字符串,整数等)。嗯..它相当简单,但这个很少出错......
那是......
直到你真正开始创建(这是代码类)。
在光谱的实际结束时,您可以在一个大类中定义所有内容并完成它......这是......直到您必须定义行为的微妙变化(门外,车库门,狗门等) )。
我的方法通常是从一个大类开始(丑陋但代码很快,我可以更快地获得工作原型)。然后,如果我需要定义一个justments或新行为或重用整个部分,那么我创建smalle元素并重构大元素以使用较小的元素而不是定义它自己的属性。
例如。我编写门类,从那里我可以创建(实例化)尽可能多的门,但它们都是相同的,行为相同。现在我意识到我还需要定义围绕铰链旋转的窗户......等一下......门也有铰链。这是我创建一个铰链类,可以由门和窗使用,并删除我在门类中定义铰链之前的任何方式。然后继续工作,直到我遇到一种情况,我可以在多个对象(句柄,框架等)之间重复使用某些部分。
根据这个经验法则,我可以快速获得代码,通常它会收敛到足以满足手头需求的粒度级别。
然后凭借经验,您可以深入了解您希望对象的粒度,而无需经常重新分解对象,这非常耗时。然而,我发现重新分解是耗时的,但从来没有像从头开始一直设计的那样多。重新分解几乎是不可避免的,因此最好尽早开始重新分解。
无论如何......我的两分钱,我希望它有所帮助。答案 12 :(得分:1)
找出何时需要创建对象的一种方法是何时用简单的语言写下您要完成的内容的简短描述。如果您对在描述中表达了问题感到高兴,那么您可以从该文本中选择对象作为候选类。然后删除那些显然不需要的东西。
当然,您通常会在SW中添加更多类,但您仍会删除一些您选择的方法,但这是我经常使用的起点。我通常最终在此之后绘制粗略的ER图,这进一步阐明了我需要哪些类。我还会查看候选类的继承目的相似性。
因此,如果你觉得有必要在简短的描述中解释钥匙孔,那么它就是一个很好的候选人。如果没有,以后可能会显然你需要一个单独的课程,但在那时你应该已经知道你在做什么了。
答案 13 :(得分:1)
只要对象只有一个目的/责任,就不应该再分开(除非它太大而不应该是这种情况)。
制作物品,只要你能分开并征服它们。如果你制作了许多小物件,你将无法处理好所有物体。另一方面,很少有大的物体不能轻易重复使用。
我的建议:练习!练习时,您将了解所需的粒度 - 对此没有一般规则。
答案 14 :(得分:1)
一般来说,如果你需要更多的信息,而不仅仅是一个的东西(不仅是旋钮的状态,还有它的颜色,它的确切位置,是否有一个键槽,能力改变其状态/行为等),然后使其成为对象。因此,当您无法通过简单的String
,Number
或Boolean
存储门需要知道的所有信息时,请将其设为值得信赖的Knob
与所有地方一样,你也有“角落案件”。我经常看到这对。两个相互关联的特性,但通常不相关。它们并不总是分组在单独的现实世界对象中。例如sortDirection
和sortField
。它们是否属于自己的对象取决于父对象所代表的内容。它是List
的可排序实现吗?好的,保持在那里。是Door
吗?好吧,我可能会把它外化。
答案 15 :(得分:1)
另一种看待它的方法是门把手是否可以互换。我会把门把手做成一个单独的物体,它是门上的一个属性。一个问题是,如果只有门可以有旋钮,你是否想要把门把手变成私人班级。我个人不喜欢在这里使用私人课程,但这是合法的可能性。通过使用单独的物体作为门上的属性,您现在可以将旋钮的实例从一个门(实例)移动到另一个门(例如,从您家中的一扇门到另一扇门交换旋钮)。
另一个有趣的方面是扩展您的层次结构...您可能有花式旋钮,可锁定旋钮等,这些都可以通过扩展您的基座门旋钮来实现。
我希望这有助于澄清你的困惑。
答案 16 :(得分:1)
您还应该考虑您需要多少个子对象。门有一个手柄而不是四个或五个手柄而不是一个手柄列表。子对象也有自己的属性吗?颜色或材料重要吗?然后最好将句柄保持为单独的对象。
答案 17 :(得分:0)
一切都是对象。有时您只是使用原始变量(int)来表示对象,有时您会创建一个数据结构(struct / class)。当然,有些物体是其他物体的一部分。
所以,是的,如果您必须在代码中使用插入密钥的中间部分,那么它也应该是代码中的对象。它可以仅由string Keyhole
表示,并且可以由class Keyhole
表示,它可以是独立的对象,并且可以是class DoorKnob
的一部分 - 但无论如何它将是一个对象。
为了决定一个对象是否应该是独立的,或者它应该是一个更大的对象的一部分,你可以问:它是否需要在更大的对象之外的上下文中,或者它只是它的一部分更大的对象的实现。
答案 18 :(得分:0)
在大多数情况下,门把手将是一个单独的物体,可以分配给门对象。
过度使用物体会说:
有锁的对象,
每种颜色都有一个颜色对象(门为“褐色”,锁定和旋钮为“银色”),
和物体(门的“木”和旋钮和锁的“钢”)
在这里,您可以看到类和对象之间的区别:
一个类是一种抽象(不是编程语言的意思)形式的东西。 您可以将某些东西称为旋钮,并且无人知道它是什么。你知道旋钮有颜色和材料。
如果您购买旋钮,手中会有一个具体的旋钮物体,具有特定的颜色和材料。您现在可以更改旋钮对象的颜色,例如把它画成黑色。
但是编程对象和现实生活中的对象存在很大差异。 这些基本示例仅有助于理解OOP的基本原理。你应该很快放松这个!
(对于那些好奇的人:矩形是正方形还是正方形矩形?)
答案 19 :(得分:0)
一切是一个对象。从夸克到电子,原子到元素,尘埃,人,汽车,世界和宇宙。
即使是想法,想法或感受也是对象。
(到目前为止显而易见的答案)
决定“决定将 deservers 作为一个对象”;我非常喜欢它必须以任何方式行事而会不止一次使用。
只要您使用不止一次,就值得成为一个功能甚至是一个对象。
此外;它会被其他东西重用吗? (对象,项目,程序等)当我决定什么应该和什么不是一个对象时,这些是我的想法。
但是,正如我上面所说,问题是微不足道的,因为一切本身就是一个对象。