Questions tagged «object-oriented»

一种使系统能够建模为一组对象的方法论,这些对象可以模块化方式进行控制和操作

10
我们应该避免将自定义对象作为参数吗?
假设我有一个自定义对象Student: public class Student{ public int _id; public String name; public int age; public float score; } 还有一个窗口Window,用于显示学生的信息: public class Window{ public void showInfo(Student student); } 它看起来很正常,但是我发现Window很难单独测试,因为它需要一个真正的Student对象来调用该函数。因此,我尝试修改showInfo,使其不直接接受Student对象: public void showInfo(int _id, String name, int age, float score); 以便更轻松地单独测试Window: showInfo(123, "abc", 45, 6.7); 但是我发现修改后的版本还有另一个问题: 修改学生(例如:添加新属性)需要修改showInfo的方法签名 如果Student具有许多属性,则Student的方法签名将非常长。 因此,使用自定义对象作为参数或接受对象中的每个属性作为参数,哪个更可维护?

9
关于“告诉,不要问”如何被认为是好的面向对象的解释
这篇博文已在Hacker News上发表,并有几篇推荐。来自C ++的大多数示例似乎与我所教的内容背道而驰。 例如示例2: 坏: def check_for_overheating(system_monitor) if system_monitor.temperature > 100 system_monitor.sound_alarms end end 与好: system_monitor.check_for_overheating class SystemMonitor def check_for_overheating if temperature > 100 sound_alarms end end end C ++中的建议是,您应该更喜欢自由函数而不是成员函数,因为它们会增加封装性。两者在语义上是相同的,那么为什么更喜欢可以访问更多状态的选择呢? 范例4: 坏: def street_name(user) if user.address user.address.street_name else 'No street name on file' end end 与好: def street_name(user) user.address.street_name end …

8
LSP vs OCP / Liskov换人VS开盘关闭
我试图理解OOP的SOLID原则,并且得出的结论是LSP和OCP有一些相似之处(如果不多说的话)。 开放/封闭原则指出“软件实体(类,模块,功能等)应为扩展而开放,但为修改而封闭”。 LSP在简单的话指出,任何情况下Foo可以用的任何实例来代替Bar它源自Foo并计划将工作同样非常的方式。 我不是专业的OOP程序员,但在我看来,只有在Bar派生自LSP Foo不会更改其中任何内容而只能扩展它的情况下,LSP才是可能的。这意味着特别是程序LSP仅在OCP为true时才为true,而OCP仅在LSP为true时才为true。那意味着他们是平等的。 如果我错了纠正我。我真的很想了解这些想法。非常感谢您的回答。

3
哪种更好的做法-辅助方法是实例还是静态?
这个问题是主观的,但是我很好奇大多数程序员是如何做到这一点的。下面的示例使用伪C#,但这也应适用于Java,C ++和其他OOP语言。 无论如何,当在我的类中编写辅助方法时,我倾向于将它们声明为静态方法,并且仅在辅助方法需要它们时才传递字段。例如,给定以下代码,我更喜欢使用方法调用#2。 class Foo { Bar _bar; public void DoSomethingWithBar() { // Method Call #1. DoSomethingWithBarImpl(); // Method Call #2. DoSomethingWithBarImpl(_bar); } private void DoSomethingWithBarImpl() { _bar.DoSomething(); } private static void DoSomethingWithBarImpl(Bar bar) { bar.DoSomething(); } } 我这样做的原因是,它使(至少在我看来)清楚地知道了helper方法可能对其他对象产生副作用-即使没有阅读其实现方法。我发现我可以快速掌握使用该实践的方法,从而帮助我进行调试。 您更喜欢在自己的代码中执行哪些操作?这样做的原因是什么?

3
与基于类的OOP相比,基于原型的OOP有何优势?
当我主要在基于类的语言的上下文中处理OOP之后第一次开始对Javascript进行编程时,我对为什么基于原型的OOP会比基于类的OOP更为困惑。 使用基于原型的OOP的结构优势是什么?(例如,在某些应用程序中,我们希望它更快或更省内存吗?) 从编码人员的角度来看,优点是什么?(例如,使用原型制作某些应用程序或扩展其他人的代码是否容易?) 请不要把这个问题看做是关于Javascript的问题(多年来存在很多与原型无关的错误)。相反,请结合原型与类的理论优势来研究它。 谢谢。

2
艾伦·凯(Alan Kay)在“ Smalltalk的早期历史”中的“分配”是什么意思?
我一直在阅读《 Smalltalk的早期历史》,并且提到了“分配”,这使我质疑其含义: 尽管OOP来自许多动机,但其中两个是核心。大型方案是为包含细节隐藏的复杂系统找到一种更好的模块方案,而小型方案是找到一种更灵活的分配方案,然后尝试将其彻底消除。 (从1960-66年开始-早期的OOP和六十年代的其他形成性思想,第一部分) 我从Simula得到的是,您现在可以用目标替换绑定和分配。您希望任何程序员做的最后一件事就是内部状态混乱,即使以图形方式呈现也是如此。相反,应该将对象呈现为更适合用作动态组件的更高级别行为的站点。(...)不幸的是,当今所谓的“面向对象程序设计”中的大部分只是带有奇特构造的旧式程序设计。许多程序现在都通过“昂贵的附加程序”来完成“分配样式”操作。 (摘自“面向对象”样式,第IV节) 我将目的解释为对象是外观,而目的是在对象上设置实例变量(即“赋值”)的任何方法(或“消息”)都违反了目的,我是否正确?第四节中的以下两个陈述似乎支持了这种解释: 一起使用的四种技术-持久状态,多态性,实例化和作为目标的方法-占据了很大的力量。这些都不要求使用“面向对象的语言”-ALGOL 68几乎可以转变为这种样式-OOPL只是将设计师的思想集中在一个特定的富有成果的方向上。但是,正确执行封装不仅是对状态抽象的承诺,而且是从编程中消除面向状态的隐喻的承诺。 ...和: 分配语句(甚至是抽象的语句)表达了非常低级的目标,需要更多的目标才能完成任务。通常,我们不希望程序员弄乱状态,无论是否模拟。 可以这样说,鼓励不透明,不可变的实例吗?还是不鼓励直接改变状态?举例来说,如果我有一个BankAccount类,它的确定有GetBalance,Deposit和Withdraw实例方法/消息; 只需确保没有SetBalance实例方法/消息?

3
为什么贫血领域模型在C#/ OOP中被认为是不好的,而在F#/ FP中却非常重要?
在关于F#的博客文章中,它表示乐趣和收益,它表示: 在功能设计中,将行为与数据分开非常重要。数据类型是简单且“哑”的。然后分别有许多作用于这些数据类型的函数。 这与面向对象的设计正好相反,在面向对象的设计中,行为和数据必须结合在一起。毕竟,这正是一个类。实际上,在真正的面向对象设计中,除了行为外,您应该什么都没有-数据是私有的,只能通过方法访问。 实际上,在OOD中,围绕数据类型的行为不足被认为是一件坏事,甚至有一个名字:“ 贫血领域模型 ”。 鉴于在C#中,我们似乎继续从F#借用,并尝试编写更多的函数式代码;为什么我们不借用分离数据/行为的想法,甚至认为它不好呢?仅仅是因为该定义不与OOP一起使用,还是有一个具体的原因在C#中是不好的,由于某些原因在F#中不适用(实际上是相反的)? (注意:我对C#/ F#中的差异特别感兴趣,因为它们可能会改变对优劣的看法,而不是对博客文章中的任一种看法持不同意见的人)。


9
退货被认为有害吗?没有它,代码可以起作用吗?
好的,标题有点clickbaity,但是我已经很认真地告诉别人,请不要踢一会儿。我喜欢它如何鼓励以真正的面向对象的方式将方法用作消息。但是,这个棘手的问题一直困扰着我。 我开始怀疑编写良好的代码是否可以同时遵循OO原则和功能原则。我正在设法调和这些想法,而我所坚持的最大症结是return。 纯函数具有两种性质: 使用相同的输入重复调用它总是得到相同的结果。这意味着它是不可变的。其状态仅设置一次。 它不会产生副作用。调用它引起的唯一变化就是产生结果。 那么,如果您发誓要使用return它来传达结果,那么如何才能完全发挥功能呢? 该出来,不问用什么有些人会考虑副作用思想工作。当我处理一个对象时,我不会询问它的内部状态。我告诉它我需要做的事情,它使用其内部状态来弄清楚该如何处理我已经告诉它要做的事情。一旦我告诉了我,我就不会问它做了什么。我只是希望它对它被告知要做的事情有所作为。 我认为“告诉,不要问”不仅仅是封装的另一个名称。当我使用时,return我不知道叫我什么。我不能说这是协议,我必须强迫它处理我的协议。在许多情况下,这表示为内部状态。即使暴露的不是确切的状态,通常也只是对状态和输入args进行一些计算。拥有一个响应界面,可以将结果整理成比内部状态或计算更有意义的结果。那就是信息传递。请参阅此示例。 回想过去,当磁盘驱动器中实际上装有磁盘,而拇指驱动器是您在汽车上做的,而车轮太冷而无法用手指触摸时,我就被教给了令人讨厌的人们如何考虑没有参数的功能。void swap(int *first, int *second)似乎很方便,但是我们鼓励我们编写返回结果的函数。因此,我坚信信念,并开始遵循。 但是现在我看到人们在构建体系结构,在该体系结构中,对象可以通过其构造方式控制结果的发送位置。这是一个示例实现。再次注入输出端口对象似乎有点像out参数的想法。但这就是告诉对象不要告诉其他对象他们所做的事情的方式。 当我第一次了解副作用时,我将其视为输出参数。有人告诉我们不要以令人惊讶的方式进行某些工作,也就是说,不遵守return result公约,以使人们感到惊讶。现在可以肯定,我知道有很多并行异步线程问题会带来副作用,但是返回实际上只是一个约定,您可以将结果压入堆栈,以便以后调用时可以将其弹出。真的就是这些。 我真正想问的是: 是return避免所有这些副作用的苦难并获得没有锁等的线程安全性的唯一方法。还是我可以跟着说,不要以纯粹的功能性方式提出要求?

8
在getter和setter里面应该允许什么?
我进入了有关getter和setter方法以及封装的有趣的Internet争论。有人说,他们应该做的只是分配(设置器)或变量访问(获取器),以使它们“纯净”并确保封装。 我是对的,这会完全破坏首先使用getter和setter的目的,应该允许进行验证和其他逻辑(当然没有奇怪的副作用)吗? 何时应进行验证? 设置值时,在设置器内部(以防止对象进入无效状态-我认为) 在设置值之前,在设置器之外 在对象内部,每次使用该值之前 是否允许设置器更改值(也许将有效值转换为某些规范的内部表示形式)?

8
在OOP之前,数据结构成员是否公开?
使用OOP语言实现数据结构(例如,队列)时,数据结构的某些成员需要为私有的(例如,队列中的项目数)。 队列也可以使用struct和在上操作的一组函数以过程语言实现struct。但是,在过程语言中,您不能将成员struct设为私有成员。使用过程语言实现的数据结构的成员是否公开了,还是有一些技巧使其私有化?

3
子类和子类型之间有什么区别?
关于这个问题的最高的答案是关于Liskov替代原理的努力,竭力区分子类型和子类。这也说明有些语言将两者混为一谈,而另一些则没有。 对于我最熟悉的面向对象语言(Python,C ++),“类型”和“类”是同义词。对于C ++,在子类型和子类之间进行区分意味着什么?举例来说,这Foo是的子类,但不是子类型FooBase。如果foo是的实例Foo,则此行: FooBase* fbPoint = &foo; 不再有效?

11
错误变量是反模式还是好的设计?
为了处理不应停止执行的几种可能的错误,我有一个error变量,客户端可以检查并使用该变量引发异常。这是反模式吗?有没有更好的方法来解决这个问题?有关此操作的示例,您可以查看PHP的mysqli API。假定正确处理了可见性问题(访问器,公共和私有范围,是类中的变量还是全局变量?)。


1
程序员为什么要使用Acme作为包,名称空间或目录名称
这可能不是愚蠢的问题,但我真的很想知道困扰我一段时间的事情的答案。 我经常看到编程示例/约定,程序员在其中创建了一个目录,acme用于放置内容。 什么Acme意思 为什么选择Acme而不选择Emca或其他? Acme是否像用于将其他OOP类分组的通用文件夹名称? 根据编程约定,该术语从何而来。据我所知,它与程序员的用户界面无关http://plan9.bell-labs.com/sys/doc/acme.html

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.