可以使用普通函数模拟OOP编程吗?与使用静态变量和匿名函数一样:http://php.net/manual/en/functions.anonymous.php
答案 0 :(得分:2)
静态变量用于编写过程代码,乍一看看起来像OOP。
OOP是一种设计模式,与您使用的语言方面无关。阅读以下文章后,您将从中受益匪浅:OOP vs Procedural Code。它解释了编写面向对象的代码(即使只有函数)。
此外,您应该知道functional programming是一个完全不同的开发范例。有这种范例的功能语言:JavaScript,Scala,Haskell,Erlang。
答案 1 :(得分:2)
我认为我能想象到的最接近的就是编写所有函数,将第一个参数作为数据结构进行操作。可以这样想:
OOP本质上只是将已知的数据结构与适当的行为耦合在一起。
因此,如果您愿意相信自己只传递函数知道如何使用的数据结构,您可以在程序上对其进行建模,每个“类”在全局空间中有两个数组,一个用于“实例”,一个用于“函数”(字面意思是一系列可调用的密钥,以他们的名字命名)。
我编写了一些代码,它们将“类”定义为基本上是方法的集合,而这些方法基本上可以处理$self
但是他们想要(只要他们都知道会发生什么)。这是一个非常酷的主意(感谢您的提问!)。注意匿名函数的使用,理论上可以将它们聚合到一个函数原型数组中,并在许多不同的类上使用(即只有一个“description”或“__toString”类,适用于所有类)。
<?php
// The "Runtime" //
function makeObject($class, $constructorArgs) {
global $classes;
$constructorArgs = (array) $constructorArgs;
$instance = $classes[$class]['instances'][] = array();
$instance['_class'] = $class;
$instance = callMethod($instance, 'construct', $constructorArgs);
return $instance;
}
function callMethod($instance, $method, $args = array()) {
global $classes;
return call_user_func_array($classes[$instance['_class']]['methods'][$method], array_merge(array($instance), $args));
}
// Class definition for "Person" //
$classes['Person'] = array();
$classes['Person']['methods'] = array();
$classes['Person']['methods']['construct'] = function($self, $name) {
$self['name'] = $name;
return $self;
};
$classes['Person']['methods']['sayHello'] = function($self)
{
echo "hello, my name is " . $self['name'] . "\n";
};
$classes['Person']['instances'] = array();
// Begin "Application" code.
// equivalent to:
// $person = new Person("sally");
// $person->sayHello();
$person = makeObject('Person', "sally");
callMethod($person, "sayHello");
这显然可以通过任何有趣和有趣的方式进行扩展。例如,您可以重做“方法”函数的结构,也可以使用$ parent参数,并允许子类调用其父级,并允许callMethod()在子级未实现时查找继承的方法。这很有趣。请注意,只有最后两行实际上是“应用程序代码”...其余的等同于声明性“设置”代码(类似于类定义)和“运行时”函数。
答案 2 :(得分:2)
是。当你到达底层时,“对象只是函数的记录”,这在编程语言理论中是众所周知的。也就是说,如果你的语言具有类似记录的功能和适当的第一类功能(即“闭包”),那么“类”只是一个返回这种记录的函数。例如,在一些伪语法中(因为我的PHP很简陋):
func Point(x, y) {
var my_x = x
var my_y = y
var this = {
getX : func() { return my_x }
getY : func() { return my_y }
move : func(dx, dy) { my_x += dx; my_y += dy }
dist : func() { return sqrt(this.getX()**2 + this.getY()**2) }
}
return this
}
var p = Point(0, 3)
p.move(2, -5)
p.getY() // -2
注意所有“方法”如何只是关闭局部变量(因此隐藏)的第一类函数。
如果你还想要继承,那么编码会更多地涉及,但仍然可以。
答案 3 :(得分:1)
是。例如,可能用功能语言重载函数在某种程度上等同于OOP中的继承。但关键是,你甚至不应该认为试图使用函数式语言编写的代码看起来像OOP。将它们视为不同的工具,以实现相同的目标。
OOP 理论上促进了更清晰的代码库,所谓的允许更容易地重用代码。 当它出现时,围绕着这些概念进行了大量宣传,许多人甚至会说今天这种概念过于夸张。功能语言在过去几年中重新获得了应有的尊重,许多人已经意识到OOP只是一个BUZZ词,绝不是代码质量的保证。
有许多编程技术和方法可以使函数编程与OOP一样优雅。对于任何项目来说,使用正确的工具是一个良好的开端,正确使用它是您应该注意的主要部分。试图使一个特定项目的代码库看起来像一个功能语言的OOP不会带来任何好处,并且必然会使某些人感到悲惨:如果不是你,那么必须维护它的人。
您的主要目标之一是让代码库尽可能易于理解,并且有许多特定于函数式编程的方法可以解决这个问题,就像OOP中的方法一样。在我(非常谦虚)的观点中,函数式编程甚至具有优势,因为它更灵活。
我已经看到并管理过相当大的项目,很高兴能够参与其中。还有一些小型的OOP项目非常难以理解。即使使用正确的工具,在错误的手中也会带来不好的结果。
我的2美分,快乐的编码!
答案 4 :(得分:1)
很多人对OOP到底是什么有不同的看法...... 我认为OOP是一种以非常特定的方式设计程序的方法,使用对象作为程序或计算的系统隐喻,它可以帮助您为最终的过程和软件灌输许多非常好,有用和强大的特性。
考虑到这一点,您可以在使用任何语言时应用OOP方法,使用某种语言比使用其他语言更容易...通常最简单的是“OOP”语言,而不是语言这会迫使你编写OOP代码(因为这是不可能的),但这会给你一系列功能,如果你想遵循OOP方法,那将会让你的生活更轻松......
最后,你需要“模拟OOP”的最困难的“事情”就是能够使用“行为”或“代码”作为数据......这可以通过很多方式实现,比如lambda函数,或第一类函数,或函数指针等......大多数现代语言至少支持其中一种。
答案 5 :(得分:1)
OOP是关于有一个构造函数,它启动一个对象,使用this
关键字“静态地”访问其他函数。
所以是的,你可以在不使用“class”,“this”或__construct等语言结构的情况下进行OOP。
正常OOP :
class Something{
public $member_var;
public function __construct(){
$this->member_var="x";
}
public function fill($strValue){
$this->member_var=$strValue;
}
}
$objInstance=new Something();
$objInstance->fill("abc");
使用过程语言结构的OOP (我已经避免了Object类远离任何OOP的东西,但是将它用于$ self类型会更好,也许能够使用 - > gt访问者,或利用引用自动传递):
function Something_constructor(&$self){
$self=array(
"member_var"=>"x",
);
}
function fill(&$self, $strValue){
$self["member_var"]=$strValue;
}
Something_constructor($arrInstance);
fill($arrInstance, "abc");
使用PHP&gt; = 5.3新的匿名函数功能,您可以在$ self数组/对象中添加成员函数作为属性,因为您可以直接调用($self["fill"]("abcde")
)。如果为$ self使用对象数据类型,则可以使用更好的访问者。
根据你设计代码的方式,这个程序风格的OOP可能会被调整为在简单的RPC场景中很好地工作(但是,构造函数永远不会返回一个可用的$ self对象/数组,所以你也可以去完整的OOP和有同样的问题)。
如果进入(object)array()路由,你可以将fill函数作为属性存储在对象中,但是你永远不会有$this
引用(不传递它作为param)或原型或任何其他类型的继承。你最好坚持使用PHP中的class关键字,没有理由去解决它。
如果你还需要继承,这就是丑陋的地方:你需要创建重命名的函数来覆盖$self
数组/对象的“类型”转换函数等。
可以做到。如果您有复杂的需求(如继承),它可能会变得非常难看。如果你有非常简单的需求,不是那么难看,甚至可能有优势。