java OOP的缺点?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2853316/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 23:09:47  来源:igfitidea点击:

Disadvantage of OOP?

javac++oopinheritance

提问by bragboy

Typically I don't want to know the specifics of the cons of OOPs, but it felt kind of weird when I had an argument at an interview I attended recently. The question that was posted to me was to tell me one disadvantage of object-oriented programming(OOP). At that time, I felt OOP to be the most matured level of programming after the procedural and functional models. So I replied to him that I don't see any negatives at all.

通常我不想知道 OOP 的缺点的细节,但是当我在最近参加的一次采访中争论时感觉有点奇怪。发布给我的问题是告诉我面向对象编程(OOP) 的一个缺点。当时觉得OOP是继过程模型和函数模型之后最成熟的编程层次。所以我回答他说我根本没有看到任何负面影响。

But the interviewer said there are few, and I asked him to list one if he does not mind. He gave an example that I don't digest well. He said that an OOP pattern does not strictly implement inheritance rules and cited the satellite/rocket example where the body parts will disintegrate periodically to remove weight during rocket launch and said that inheritance does not support this.

但是面试官说很少,如果他不介意,我让他列出一个。他举了一个我消化不好的例子。他说 OOP 模式没有严格执行继承规则,并引用了卫星/火箭的例子,其中身体部位会在火箭发射期间定期分解以减轻重量,并表示继承不支持这一点。

His example kind of felt very weird to me, the reason being the application of inheritance to this example.

他的例子让我觉得很奇怪,原因是对这个例子应用了继承。

I understand that the example he gave hardly had any sense at all, but I had this doubt -

我知道他举的例子几乎没有任何意义,但我有这个疑问——

Can we unplug class hierarchies dynamically (I am kind of confident in Java it's not possible) in an ideal object-oriented design?

在理想的面向对象设计中,我们能否动态地取消类层次结构(我对 Java 有点信心,这是不可能的)?

采纳答案by Uri

I'm not fully understanding his example.

我没有完全理解他的例子。

However, it's important to understand that OOP is very effective for things that can be modeled naturally with it, and is very ineffective for other things (e.g., crosscutting concerns or aspects). That is one disadvantage of OOP. Another is that it often incurs some runtime cost due to dynamic dispatching.

然而,重要的是要了解 OOP 对于可以用它自然建模的事物非常有效,而对于其他事物(例如,横切关注点或方面)则非常无效。这是 OOP 的缺点之一。另一个原因是,由于动态调度,它经常会产生一些运行时成本。

In addition, it is very easy to abuse OOP to do nonsensible abstractions. Having a rocket inherit from a body is one example. My experience is that novice developers either don't trust and don't use inheritance, or that they are over-eager and use it incorrectly, when other behaviors (like aggregation) are more appropriate. Over time, experience and understanding of the mechanism improve.

此外,很容易滥用 OOP 进行无意义的抽象。让火箭继承身体就是一个例子。我的经验是,当其他行为(如聚合)更合适时,新手开发人员要么不信任也不使用继承,要么过于急切并错误地使用它。随着时间的推移,对该机制的经验和理解会得到改善。

I'm not sure what he meant by "OOP pattern does not strictly implement inheritance rules", since OOP is not a pattern. One potential issue is that one can write a subtype that can violate Liskov's principle of substitution, so that an overridding method does not behave "at least" like the overridden method. There is no way to automatically check for this so it is possible to write code that violates OOP principles.

我不确定他所说的“OOP 模式没有严格实现继承规则”是什么意思,因为 OOP 不是一种模式。一个潜在的问题是,人们可以编写一个违反 Liskov 替换原则的子类型,因此覆盖方法的行为“至少”不像被覆盖的方法。没有办法自动检查这一点,因此有可能编写违反 OOP 原则的代码。

As for your final question "Can we unplug class hierarchies in an ideal Object Oriented Design?", I'm not sure what you mean here. If you're asking about changing the hierarchy at runtime, and making it so that a subtyping relation no longer exists from some point in the execution, then yes. It is possible with certain languages such as Smalltalk. Some would argue that this is "More OOP". In smalltalk, the 'methods' supported by a type are determined at the point of method call based on the current hierarchy and the current contents of each class. While I love smalltalk, this is one feature that I'm not crazy about, since I prefer compile-time checking with less runtime surprises.

至于您的最后一个问题“我们可以在理想的面向对象设计中取消类层次结构吗?”,我不确定您在这里的意思。如果您询问在运行时更改层次结构,并使其从执行中的某个点开始不再存在子类型关系,那么是的。使用某些语言(例如 Smalltalk)是可能的。有些人会争辩说这是“更多的 OOP”。在 smalltalk 中,类型支持的“方法”是在方法调用点根据当前层次结构和每个类的当前内容确定的。虽然我喜欢 smalltalk,但这是我并不喜欢的一项功能,因为我更喜欢编译时检查,运行时出现较少的意外。

回答by LBushkin

Just because you have a hammer, doesn't mean everything is a nail.

仅仅因为你有一把锤子,并不意味着一切都是钉子。

I've found that many people often confuse when to apply compositionvs. inheritancewhen using OOP as a programming style.The example you cite from the interview question appears to be a case of this exact kind of confusion.

我发现很多人在使用 OOP 作为编程风格时经常混淆何时应用组合继承你从面试问题中引用的例子似乎就是这种混淆的一个例子。

One thing I've learned with experience, is that while inheritance is a nice paradigm for expression "IS-A" relationships between entities in a design, it's often better to favor composition rather than inheritance.

我从经验中学到的一件事是,虽然继承是表达设计中实体之间“IS-A”关系的一个很好的范例,但通常更倾向于组合而不是继承

But let's examine the crux of the interviewers question though: when is OOP a poort choice of paradigm?.

但是,让我们来看看面试官问题的症结所在:OOP 什么时候是最糟糕的范式选择?.

OOP works best with large-scale, multi-developer, multi-module projects.For "development in the small" - such as scripting or transformative processing, it can require a good deal of overhead without necessarily adding value. But even in these cases, unless you're writing throw-away code, I would argue that large solution often evolve from smaller ones, so establishing structure and separation of concerns early on can save you grief later.

OOP 最适用于大型、多开发人员、多模块的项目。对于“小规模开发”——例如脚本编写或转换处理,它可能需要大量开销,但不一定会增加价值。但即使在这些情况下,除非您编写一次性代码,否则我认为大型解决方案通常是从较小的解决方案演变而来的,因此尽早建立结构和关注点分离可以避免以后的痛苦。

Ultimately, OOP programming also requires a certain level of design rigor and planning, as well as an understanding of the core principles of object orientation. If you're unwilling to take the time to study and understand those principles ... well, perhaps then OOP programming is notfor you.

归根结底,OOP 编程还需要一定程度的设计严谨和规划,以及对面向对象核心原则的理解。如果您不愿意花时间学习和理解这些原则……好吧,也许 OOP 编程适合您。

Beyond that, certain kinds of problems also lend themselves to alternative programming styles. For example, transformative processing is quite ammendable to the functional style of programming- in which a results is computed and passed to successive transformation steps to produce a final result. Problems where you have to search or query a domain for certain matching information are ammenable to query languages(like SQL) in which you describe your intent declaratively rather than imperatively.

除此之外,某些类型的问题也适用于其他编程风格。例如,转换处理非常适合编程函数式风格- 在其中计算结果并将其传递给连续的转换步骤以产生最终结果。您必须搜索或查询某个域以获取某些匹配信息的问题可以通过查询语言(如 SQL)来解决,在这些语言中您以声明方式而非命令方式描述您的意图。

Being able to recognize which kind of problem you are solving goes a long way towards choosing which kind of language or tool to use.The right tools can make a job much easier ... the wrong one can make it harder - or impossible.

能够识别您正在解决的问题类型对于选择使用哪种语言或工具大有帮助。正确的工具可以使工作变得更容易……错误的工具会使工作变得更难——或者不可能。

回答by Chuck

Although I agree with the interviewer's conclusion (OOP is flawed), his logic appears to be nonsense. It sounds like he's criticizing something he doesn't understand, because no competent OO programmer would make a rocket inherit from its thrusters.

虽然我同意面试官的结论(OOP有缺陷),但他的逻辑似乎是无稽之谈。听起来他在批评他不理解的东西,因为没有称职的面向对象程序员会让火箭继承其推进器。

People have made good criticisms against OOP, though. For example, Steve Yegge's Execution in the Kingdom of Nouns.

不过,人们对 OOP 提出了很好的批评。例如,史蒂夫耶格在名词王国处决

回答by jmucchiello

His example makes no sense. A rocket doesn't inherit from a body. It "has" a body. That's containment. So a some point you would "delete" the part attached to the rocket as it was jettisoned.

他的例子毫无意义。火箭不会从身体继承。它“有”一个身体。这就是遏制。所以在某个时候你会“删除”连接到火箭上的部分,因为它被抛弃了。

回答by Robben_Ford_Fan_boy

Although I don't fully understand the example given, as it sounds like composition to me I will give a disadvantage of OOP

虽然我不完全理解给出的例子,但对我来说听起来像是组合,我会给出 OOP 的一个缺点

OO is hard to test

OO 很难测试

  • No direct access to read/write class variables/attributes - may need to introduce getters and seeters which breaks incapsulation.

  • Inheritance can change the behavior of a method in a subclass

  • Objects have state. It can be hard to generate these states as we depend on the public interface.

  • Classes with loh cohesion can be hard to test as this could mean that the class does more than is specified.

  • 无法直接访问读/写类变量/属性 - 可能需要引入破坏封装的 getter 和 seeter。

  • 继承可以改变子类中方法的行为

  • 对象有状态。由于我们依赖公共接口,因此很难生成这些状态。

  • 具有 loh 内聚力的类可能很难测试,因为这可能意味着该类的功能超出了指定的范围。

回答by Moonshield

I can kinda see the point he was driving at. I think the argument was basically centred around the disadvantage of inheritance - if you're not careful, or if you inherit too many times to keep extending functionality you can end up with a bloated mess of a class with a load of redundant features and lack of cohesion.

我可以看出他开车的目的。我认为争论基本上集中在继承的缺点上——如果你不小心,或者如果你继承太多次以保持扩展功能,你最终可能会导致一个类的臃肿混乱,具有大量冗余特性和缺乏的凝聚力。

His analogy works if you consider that, once the rocket has burned the fuel in a segment, the segment becomes redundant and therefore dead-weight. The rocket can jettison the segment, but I don't think it's possible to exclude sections of a class you don't want to inherit (although correct me if I'm wrong, because it sounds useful).

如果你考虑到,一旦火箭燃烧了一个段中的燃料,这个段就会变得多余,因此是自重的,他的类比是有效的。火箭可以丢弃该段,但我认为不可能排除您不想继承的类的部分(尽管如果我错了,请纠正我,因为这听起来很有用)。

回答by meriton

Might the rocket example have alluded to the fact that in many object oriented languages, an object's type is immutable? That is, if I have a Studentobject, and the person it represents finishes her studies and becomes an employee, I can not turn the Studentobject into an Employeeobject. I have to create a new one, lose object identity in the process, and consequently have to update all references pointing to the former student.

火箭的例子是否暗示了这样一个事实,即在许多面向对象的语言中,对象的类型是不可变的?也就是说,如果我有一个Student对象,并且它所代表的人完成学业并成为一名员工,我无法将Student对象变成Employee对象。我必须创建一个新的,在此过程中丢失对象标识,因此必须更新指向前学生的所有引用。

Of course, such a feature would interfere with static typing (the type invariant that an object's type is a subtype of the static type of any reference pointing to it). But in some contexts the flexibility might be worth that.

当然,这样的特性会干扰静态类型(类型不变量,即对象的类型是指向它的任何引用的静态类型的子类型)。但在某些情况下,灵活性可能值得。

回答by Jim L

I'm sure I've never heard of a statically typed language like Java that is capable of morphing an object into another while leaving the object reference intact, but I'm sure you can fake it with delegates etc. That said, without some fundamentally good thought, it probably would be a mess.

我敢肯定我从来没有听说过像 Java 这样的静态类型语言,它能够将一个对象变形为另一个对象,同时保持对象引用不变,但我确定你可以用委托等来伪造它。也就是说,没有一些基本上很好的想法,它可能会一团糟。

I can't know how the interviewer presented the question or how you responded, but one of OOP's biggest short comings isn't really OOP itself. It's the poor usage of OOP and bad "IS-A" relationships people try to create. If the only reason you can come up with to create an inheritance hierarchy is reuse of code, it's a poor reason. AOP can be argued to be a better approach for that. (before you flame or down vote, please note I said "can be")

我不知道面试官如何提出问题或您如何回答,但 OOP 最大的缺点之一并不是真正的 OOP 本身。这是人们试图创建的 OOP 使用不当和糟糕的“IS-A”关系。如果您能想出的创建继承层次结构的唯一原因是代码的重用,那么这是一个糟糕的理由。AOP 可以说是一种更好的方法。(在您发起或否决投票之前,请注意我说的是“可以”)

OOP is about the interface and type, not about the implementation. Knowing that an object can return a list of job candidates is all I need to know. Whether that comes from an RDBMS, column oriented db, web service, or even spreadsheet is immaterial. I know I can pass that object as a parameter to other methods and they can call "FetchJobCandidates" and know it will get job candidates. There are pitfalls along the way, but mostly if you think of classes based on what they expose to the rest of the world rather than what they do internally, you're on a better footing IMO.

OOP 是关于接口和类型的,而不是关于实现的。我只需要知道一个对象可以返回求职者列表。这是否来自 RDBMS、面向列的数据库、Web 服务,甚至电子表格都无关紧要。我知道我可以将该对象作为参数传递给其他方法,他们可以调用“FetchJobCandidates”并知道它将获得求职者。在此过程中存在陷阱,但大多数情况下,如果您根据它们向世界其他地方展示的内容而不是它们在内部做什么来考虑类,那么 IMO 的基础就更好了。

回答by paul

Can we just say use this in OOP?

我们可以说在 OOP 中使用它吗?

RocketShip.BodyPart1 = nothing or

RocketShip.BodyPart1 = 没有或

RocketShip.BodyPart1.isDetached = false?

RocketShip.BodyPart1.isDetached = false?

I believe it is not the OOP itself is the fault but it's the limitation(s) of the programming language used on how it is being implemented.

我相信这不是 OOP 本身的问题,而是所使用的编程语言对其实现方式的限制。

回答by fortran

I think it's main disadvantage comes straight from its power. One of the most common things done in OOP is to replace parent classes with derived classes in some places, to specialise the behaviour of the code. Well, if not done carefully, it's easy to invalidate some of the assumptions made in the caller code; and that could be very difficult to spot while reviewing the code, because the types you're seeing declared are not the ones actually being used.

我认为它的主要缺点直接来自它的力量。在 OOP 中最常见的事情之一是在某些地方用派生类替换父类,以专门化代码的行为。好吧,如果不小心完成,很容易使调用者代码中的一些假设无效;在代码时可能很难发现这一点,因为您看到的声明类型并不是实际使用的类型。

In brief: polymorphism can be made not explicit and thus easy to overlook weird behaviours in the derived classes.

简而言之:可以使多态不显式,因此很容易忽略派生类中的奇怪行为。