Questions tagged «object-oriented»

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

12
为什么在学习面向对象编程之前,我们必须学习过程编程[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 6年前关闭。 我现在是一所IT大学的四年级学生,当我和我的教授谈论这个话题时,他拒绝了我的意见,并给了我很大的批评(在我的大学里,我们被教导C(ANSI)(在程序编程课-大学一年级(C ++之前)(第二年OOP班)及其他... 但是在我13岁那年,我的兄弟首先接受了Java的培训,而没有别的。现在,他几乎可以完成普通的二年级学生使用Java可以完成的所有工作。 对于您的专业人士,我想知道您为什么认为我们应该首先学习过程编程。

12
如何向非技术人员解释OOP概念?
已锁定。该问题及其答案被锁定,因为该问题是题外话,但具有历史意义。它目前不接受新的答案或互动。 我经常尝试避免告诉别人我是程序员,因为大多数时候我都会向他们解释这到底意味着什么。当我告诉他们我使用Java编程时,他们经常问有关该语言以及它与x和y有何区别的一般性问题。我也不善于解释事物,因为1)我在该领域没有太多经验,并且2)我真的讨厌向非技术人员解释事物。 他们说,一旦您向其他人解释事物,您便真正理解了事物,在这种情况下,您将如何向非技术人员解释OOP术语和概念?

4
跨对象边界的信息泄漏
很多时候,我的业务对象往往会遇到信息需要经常跨越对象边界的情况。在进行OO时,我们希望信息位于一个对象中,并且处理该信息的所有代码应尽可能在该对象中。但是,业务规则没有遵循该原则,这给我带来了麻烦。 作为示例,假设我们有一个包含多个OrderItems的Order,该OrderItems引用一个具有价格的InventoryItem。我调用了Order.GetTotal(),它对OrderItem.GetPrice()的结果求和,该结果乘以InventoryItem.GetPrice()乘以数量。到目前为止,一切都很好。 但随后我们发现有些商品以一交易两卖。我们可以通过让OrderItem.GetPrice()做类似InventoryItem.GetPrice(quantage)的事情并让InventoryItem处理来解决这个问题。 但是,然后我们发现二对一交易仅持续特定时间段。该时间段必须基于订单日期。现在我们将OrderItem.GetPrice()更改为InventoryItem.GetPrice(quatity,order.GetDate()) 但是然后我们需要根据客户在系统中待了多长时间来支持不同的价格:InventoryItem.GetPrice(数量,order.GetDate(),order.GetCustomer()) 但是,事实证明,一对一交易不仅适用于购买多个相同库存物品,而且适用于InventoryCategory中任何物品的多个交易。在这一点上,我们举起手来,只给InventoryItem订购项,并使其通过访问器在对象引用图上移动,以获取其需求的信息:InventoryItem.GetPrice(this) TL; DR我希望对象之间的耦合度低,但是业务规则经常迫使我从各地访问信息以做出特定决策。 有好的技巧可以解决这个问题吗?其他人也会发现同样的问题吗?

4
领域驱动设计中的重构
已关闭。这个问题需要细节或说明。它当前不接受答案。 想改善这个问题吗?添加细节并通过编辑此帖子来澄清问题。 6年前关闭。 我刚刚开始从事一个项目,我们正在使用领域驱动的设计(由Eric Evans在“ 领域驱动的设计:解决软件核心中的复杂性”中定义。我相信我们的项目肯定是该设计的候选人就像埃文斯在书中描述的那样。 我在不断重构的想法中挣扎。 我知道在任何项目中重构都是必不可少的,随着软件的改变,重构将不可避免地发生。但是,根据我的经验,重构是在开发团队的需求发生变化时发生的,而不是对领域变化的理解(Evans称之为“重构以获得更大的洞察力”)。我最关心的是对领域模型的理解方面的突破。我知道进行小的更改,但是如果需要对模型进行较大的更改怎么办? 在说服更清晰的域模型之后,应该说服自己(和其他人)重构的有效方法是什么?毕竟,为了改善代码的组织或性能而进行的重构可能与无处不在的语言代码的表达方式完全不同。有时似乎没有足够的时间进行重构。 幸运的是,SCRUM使它可以进行重构。SCRUM的迭代性质使其易于构建一小块并进行更改。但是随着时间的流逝,该片段会变大,如果您在该片段太大而又难以更改时又取得突破,该怎么办? 是否有人从事采用领域驱动设计的项目?如果是这样,那么对此有所了解将是很棒的。我特别想听听一些成功的故事,因为DDD似乎很难解决。 谢谢!


4
C ++处理大型模板实现的首选方法
通常,在声明C ++类时,最佳实践是仅将声明放入头文件中,并将实现放入源文件中。但是,这种设计模型似乎不适用于模板类。 在网上查找时,对于管理模板类的最佳方法似乎有两种意见: 1.标头中的整个声明和实现。 这相当简单,但是我认为,当模板变大时,很难维护和编辑代码文件。 2.将实现写入末尾包含的模板包含文件(.tpp)中。 对我来说,这似乎是一个更好的解决方案,但似乎并未得到广泛应用。是否存在这种方法不及格的原因? 我知道很多时候,代码风格是由个人喜好或传统风格决定的。我正在开始一个新项目(将旧的C项目移植到C ++),并且我对OO设计比较陌生,并且希望从一开始就遵循最佳实践。


6
抽象类应包含哪些代码?
最近,我对抽象类的使用感到困扰。 有时,会预先创建一个抽象类,并将其作为派生类工作方式的模板。这意味着或多或少地,它们提供了一些高级功能,但是遗漏了某些细节要由派生类实现。抽象类通过放置一些抽象方法来定义对这些细节的需求。在这种情况下,抽象类的工作原理类似于蓝图,功能的高级描述或您想要的任何名称。它不能单独使用,而必须专门用于定义高层实现中遗漏的细节。 在另一些时候,碰巧抽象类是在创建一些“派生”类之后创建的(由于父/抽象类还不存在,所以还没有派生出来,但是您知道我的意思)。在这些情况下,抽象类通常用作放置当前派生类所包含的任何常见代码的地方。 做出上述观察后,我想知道这两个案例中的哪一个应该成为规则。是否应该仅由于它们当前在所有派生类中都是通用的,而将某种细节冒充到抽象类?是否应该存在不属于高级功能的通用代码? 对于抽象类本身可能没有意义的代码是否应该仅仅因为它对派生类是通用的而存在呢? 让我举个例子:抽象类A有一个方法a()和一个抽象方法aq()。在派生类AB和AC中,方法aq()都使用方法b()。b()应该移到A吗?如果是的话,那么如果有人只看着A(假装AB和AC不在那儿),那么b()的存在就没有多大意义了!这是坏事吗?有人应该能够在不访问派生类的情况下浏览抽象类并了解发生了什么吗? 老实说,在提出这个问题时,我倾向于认为编写一个有意义的抽象类而不必查看派生类是一个干净的代码和干净的体系结构的问题。我真的不喜欢抽象类的想法,它像所有代码的转储一样在所有派生类中都很常见。 您如何看待/实践?

2
只有吸气剂的接口有代码气味吗?
(我已经看到了这个问题,但是第一个答案更多的是关于自动属性而不是设计,而第二个答案则是向使用者隐藏数据存储代码,我不确定这是我想要的/我的代码做了什么,所以我想听听其他意见) 我有两个非常相似的实体,HolidayDiscount和RentalDiscount,它们表示长度折扣,即“如果至少持续numberOfDays使用percent折扣,则适用”。这些表有不同的父实体,并且在不同的地方使用,但是在使用它们的地方,有一种通用的逻辑来获取最大的适用折扣。例如,a HolidayOffer具有多个HolidayDiscounts,在计算其成本时,我们需要找出适用的折扣。租金和相同RentalDiscounts。 由于逻辑相同,因此我想将其放在一个地方。这就是以下方法,谓词和比较器的作用: Optional<LengthDiscount> getMaxApplicableLengthDiscount(List<LengthDiscount> discounts, int daysToStay) { if (discounts.isEmpty()) { return Optional.empty(); } return discounts.stream() .filter(new DiscountIsApplicablePredicate(daysToStay)) .max(new DiscountMinDaysComparator()); } public class DiscountIsApplicablePredicate implements Predicate<LengthDiscount> { private final long daysToStay; public DiscountIsApplicablePredicate(long daysToStay) { this.daysToStay = daysToStay; } @Override public boolean test(LengthDiscount discount) { return daysToStay >= …

3
将构建器和流体接口与对象初始化器一起使用是否有意义?
在Java和C#中,您可以创建具有可在初始化时设置的属性的对象,方法是定义带参数的构造函数,构造对象后定义每个属性,或使用builder / fluid接口模式。但是,C#3引入了对象和集合初始化程序,这意味着构建器模式在很大程度上没有用。在没有初始化程序的语言中,可以实现一个生成器,然后像这样使用它: Vehicle v = new Vehicle.Builder() .manufacturer("Toyota") .model("Camry") .year(1997) .colour(CarColours.Red) .addSpecialFeature(new Feature.CDPlayer()) .addSpecialFeature(new Feature.SeatWarmer(4)) .build(); 相反,在C#中,可以这样写: var vehicle = new Vehicle { Manufacturer = "Toyota", Model = "Camry", Year = 1997, Colour = CarColours.Red, SpecialFeatures = new List<SpecialFeature> { new Feature.CDPlayer(), new Feature.SeatWarmer { Seats = 4 } …

2
JavaScript中辅助函数的推荐方法是什么?
推荐的辅助功能方法是什么?我想选择一种技术,然后运行它来创建我的新“类”。 这是我所考虑的设计选项: 选项1:外部范围内的Helper函数,使用实例的上下文进行调用 function createPane (pane) { // logic to create pane var proto = Object.create(this.paneList); $.extend(paneProto, pane); return paneProto; } Panes.prototype.initialize = function (panes) { var _this = this; _.each(panes, function () { _this.panes.push(createPane.call(_this, this)); }); } 优点:简单的语法。createPane未在实例上发布。 缺点: createPane在其他范围内均可访问。 选项2:关闭时的Helper函数,使用实例的上下文进行调用 Panes.prototype.initialize = (function () { function createPane (pane) …

5
OOP:在哪些情况下,基于类的设计比基于接口的设计更好?
我正在阅读 JDOM的网站。 为什么用具体的类而不是接口来定义JDOM API? Jason Hunter总结了针对JDOM的基于接口的API的论点: 使用接口,所有东西都变成了工厂,必须将元素“导入”到新文档中,而不是仅仅添加元素,不能保证诸如长期序列化之类的功能,因此清单还在继续。 我们实际上是从接口开始的。在对某些同伴的发行前审查中,我们收到了反馈,应该尝试具体的课程。我们做到了,并且设计对此要好得多。 我是初学者。到目前为止,我所听到的所有建议都建议不要将设计与具体类一起使用。 可能在某些地方使用具体的类是适当的。是否存在在设计中使用具体类的常见类问题?

4
为什么通过静态方法传递对象会有好处?
为什么使用静态方法并将引用作为参数传递给对象而不是在对象上调用该方法会有好处? 为了阐明我的意思,请考虑以下课程: public class SomeClass { private double someValue; public SomeClass() { // Some constructor in which someValue is set } public void incrementValue() { someValue++; } } 与使用静态方法的此替代实现相比: public class SomeClass { private double someValue; public SomeClass() { // Some constructor in which someValue is set } public static …

4
重命名方法可以保留封装吗?
我正在阅读此页面,了解何时需要使用getter / setter,并且OP提供了以下代码示例: class Fridge { int cheese; void set_cheese(int _cheese) { cheese = _cheese; } int get_cheese() { return cheese; } } void go_shopping(Fridge fridge) { fridge.set_cheese(fridge.get_cheese() + 5); } 该接受的答案状态: 顺便说一句,在你的榜样,我会给类Fridge的 putCheese()和takeCheese()方法,而不是get_cheese() 和set_cheese()。这样您将仍然具有封装。 如何封装从对get / set重命名它来保存putCheese()/ takeCheese()你显然获取/设置一个值,那么为什么不干脆把它作为对get / set? 在相同的答案中,它还指出: 拥有getter和setter方法本身并不会破坏封装。破坏封装的方法是自动为每个数据成员(Java术语中的每个字段)添加一个getter和setter,而无需考虑任何问题。 在这种情况下,我们只有一个变量,cheese并且您可能想将奶酪拿回冰箱,所以在这种情况下,一对get / set是合理的。

6
如果我的对象是可变的,在函数式编程的上下文中会出什么问题?
我可以看到可变对象与不可变对象(如不可变对象)的好处,消除了由于共享和可写状态而导致的多线程编程中的许多疑难解答问题。相反,可变对象有助于处理对象的身份,而不是每次都创建新的副本,因此特别是对于较大的对象,还可以提高性能和内存使用率。 我想了解的一件事是,在函数式编程的上下文中拥有可变对象可能会出错。像告诉我的要点之一是,以不同顺序调用函数的结果不是确定性的。 我正在寻找一个真正的具体示例,其中很明显在函数编程中使用可变对象会导致什么问题。基本上,如果它不好,那么不管是面向对象还是功能编程范例都不好,对吗? 我相信,在我自己的发言下面,我可以回答这个问题。但是我仍然需要一些例子,以便我能更自然地感受到。 OO通过诸如封装,多态等工具帮助管理依赖性并编写更容易维护的程序。 函数式编程也具有促进可维护代码的动机,但是通过使用样式消除了使用OO工具和技术的需要-我认为其中之一是通过最小化副作用,纯函数等。

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.