面向对象语言的非面向对象编程


15

最近,我被分配了一项任务,即使用面向对象编程来创建具有加,减,乘,除和乘幂功能的计算器。我成功完成了这项任务。但是之后,我重新编程了整个程序,而没有使用面向对象的技术/方法

我注意到我的代码长度大大减少了,这是可以理解的。所以我的问题是,什么时候应该使用面向对象编程?是否可以使用面向对象的语言来创建没有面向对象的程序?请帮助我解决这一问题。

PS:我不是要在这里告诉我面向对象编程优于过程编程的优点。


12
绝对没有理由避免根据需要应用不同的技术。作为程序员,您需要根据具体情况权衡利弊。它经常归结为个人风格。
ChaosPandion 2014年

3
我从来没有遇到过问题。对于团队和/或其他架构,语言几乎总是一种规定的工具。


8
无论是否使用OO技术,实施相同的程序都是学习一些东西的练习,我不明白为什么这里的某些人似乎拒绝这样做或对您投反对票。但是,您的问题的问题在于,这里已经以不同的形式多次提出了这个问题。尽管您否认了这一点,但是您问的是面向对象编程优于过程编程的优点。C ++不是一种OO语言,它是一种混合语言。
布朗

3
添加一个功能来显示您输入的公式,然后添加一个平方根函数(不要先这样做,否则会作弊。),然后告诉我们您的想法。
JeffO 2014年

Answers:


25

C ++不只是“一种” OO语言,它还是一种多范式语言。因此,它使您可以决定是否支持OO编程,或将二者混合使用。使用OO技术可以为程序增加更多结构-当程序达到一定大小或复杂度时,您将从中受益。但是,这种额外的结构是以额外的代码行为代价的。因此,对于“小型”程序来说,最好的方法通常是首先以非OO风格实施它们,然后在程序开始发展多年后,再添加越来越多的OO技术(“练习”可能不会发生)。 ”程序,但这是许多业务程序的典型生命周期)。

棘手的部分是不要错过程序复杂性达到要求更多结构的大小的时间点。否则,您将获得大量的意大利面条代码。


如果简单的“锻炼”程序开始发展,最好的方法就是以一种可以在以后分解的方式来实现它。感谢您的分享:) +1
FaizanRabbani 2014年

@CarlSmith:绝对。但是,当我写下答案时,我尝试着眼于实际问题的重点和规模。
布朗

10

专业程序员如何判断是否要进行OOP?这对我真的很有帮助。

对我来说,有两个决定点。首先,有时一开始就会很明显。将会有很多相似的类型,它们都共享在实现细节上差异很大的通用方法。例如,我正在构建工作流系统,并且我需要能够执行任意任务。为了运行任务,我使用Execute()抽象方法实现了每个任务都继承自的基类。继承的类提供了实现,但是工作流系统可以在不知道正在运行哪种任务的情况下开始执行。

但是,大多数项目并没有那么明确。第二个决策点是,当项目的一个子集变成大量的if-then语句或switch-case语句时,特别是当这些if-then语句需要大量安装代码才能正确运行时。我感到自己开始迷失自己想要完成的工作的逻辑,并且代码开始变得脆弱。到那时,通常标志着是时候将代码重构为具有特定实现的基类了。

切换到面向对象样式而不是功能样式的很大一部分是将if-then语句转换为“运行此操作”语句。您无需告诉大量的if-then语句,而是告诉代码运行其动作。实际执行哪个操作取决于您提供的实现。

例如,这是C#风格的伪代码的功能风格:

if ( action == "email" ) { 
    callEmailFunction(userInfo);
}
else if ( action == "sms" ) { 
    callSmsFunction(userInfo);
}
else if ( action == "web" ) { 
    endpoint = "http://127.0.0.1/confirm";
    confirmWeb(endpoint, userinfo);
} 
...

但是也许您可以将其重写为如下形式:

interface IConfirmable {
    void Confirm(UserInfo userinfo);
}

public class ConfirmEmail : IConfirmable { 
    public void Confirm(UserInfo userinfo) {
        // do the appropriate thing to confirm via email
    }
}

public class ConfirmSms : IConfirmable { 
    public void Confirm(UserInfo userinfo) {
        // do the appropriate thing to confirm via email
    }
}

public class ConfirmWeb : IConfirmable { 
    // this is a constructor
    public ConfirmWeb(string endpoint) { 
        ...
    }

    public void Confirm(UserInfo userinfo) {
        // do the appropriate thing to confirm via web
    }
} 

然后代码本身:

// An implementation that decides which implementation of the base class to use
// This replaces the if-then statements in the functional programmming.
IConfirmable confirmer = ConfirmerFactory.GetConfirmer();

// get the userinfo however you get it, 
// which would be the same way you get it in the functional example.
UserInfo userinfo = ...;

// perform the action.
confirmer.Confirm(userinfo);

现在,如果if-then内的代码很少,这似乎需要花费很多精力。而且,如果if-then中的代码很少,那是正确的:对于难以理解的代码,这需要大量工作。

但是,当您有多个动作而不只是Confirm()需要执行的方法时,面向对象的样式确实会发光。也许您有一个初始化例程,三个或多个可以运行的动作方法以及一个Cleanup()方法。基本算法是相同的,不同之处在于它对实现通用基类的适当对象进行了调用。现在,您开始看到面向对象样式的真正好处:与在每个步骤中检查if-then语句相比,基本算法易于阅读。


+1进行详细分析。:)我对此没有什么想法。
FaizanRabbani 2014年

1
撇开:请停止在每个答案上发布“谢谢”评论。我们宁愿只关注问题和答案,而不是讨论。
菲利普·肯德尔2014年

5
这个例子比功能性更重要。
OrangeDog 2014年


1
请注意,当您倾向于一堆if / else或switch语句时,始终可以考虑使用某种lookupt表。因此,另一种重写方式遵循var dict = new Dictionary<string,Action<UserInfo>{ { "email", callEmailFunction }, { "sms", callSmsFunction } }; dict[ action ]( userInfo );(dict可以是静态的,省略了错误处理)
stijn 2014年

3

是的,只要您的项目范围众所周知或受到限制,使用旧样式代码是完全正常的。如果您打算扩展程序或项目,那么OOP是一种方法,因为您可以无缝地维护和扩展代码,另一方面,如果您计划了代码,并且得出的结论是,您永远不会计划扩展程序的可扩展性。您进行的项目,然后编写没有OOP的代码就足够了。这并不意味着如果您使用非OOP方法就永远无法升级项目,但这将是一件乏味的事情。OOP可以帮助我们将我们的概念形象化,就像它是现实生活中的有机体一样,因为我们对这些概念的了解比其他任何事物都更好。


1
“这并不意味着如果您使用非OOP方法,您将永远无法升级您的项目,但这将是一件繁琐的事情。”:当大多数扩展涉及添加新类(例如,向其中添加新的小部件)时,OOP有助于扩展您的项目。 GUI)。当大多数扩展都涉及添加新操作时,程序设计可能会更加有效。
Giorgio 2014年

1
从什么时候起“不面向对象”被称为“旧样式”?
DanielSank 2014年
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.