这是我很久以来的一个问题。
我想问这个问题很久了,我发布这个问题是希望它不会被关闭,因为它是基于意见的......如果发生这种情况,它可能是我的答案:不。
我的问题是,我们是否可以在严格意义上谈论 PHP 中的面向对象编程 (OOP),或者相反,是否只能在 PHP 中应用一些 OOP 原则。
我希望得到基于文件和证据的答案(如果有的话)。
当我看到有关它的 PHP 手册的示例或所谓的魔法方法时,它给人的印象是违反了基本的 OOP 概念,就像创建setters
公共访问的情况一样。
具体问题如下:我们可以说使用 PHP 可以进行严格意义上的 OOP 吗?为什么?
要回答这个问题,让我们检查几点:
1)引用PHP文档:
根据文档,从 PHP 5 开始,我们有一个完整的对象模型:
__get()
__set()
__call()
__construct()
PHP POO ESTRICTO + 1;
2)OOP基础知识及其在PHP中的作用:
在 OOP 中,我们可以找到将语言视为 OO 的基本特征,其中包括:
1)抽象
2)继承
3)封装
3) 隐藏
4) 多态性
5) 模块化
6)垃圾收集
Lei 表示,OOP 理论家将 3 个要点(粗体部分)作为 OOP 的基础。
现在,让我们检查一下 PHP 是否满足基本要求:
在 PHP 中使用 OOP 的基础知识:
OOP 的 3 个基本原理得到了满足。
PHP POO ESTRICTO + 1;
3)魔术方法VS类方法
要访问类的属性,我们有两种方法,经典方法和魔术方法:
经典方法:在这个方法中,我们定义了自己的
getters
andsetters
:魔术方法:在这个方法中我们使用了 PHP 带来的魔术方法,例如
__get()
and__set()
:我什么时候使用什么样的方法?:
答案可在 PHP 官方文档的“重载”部分找到。
但首先让我们了解一些基本概念:
什么是超载?:
那么PHP中有重载吗?:
不,让我们记住 PHP 没有输入:
因此,在 PHP 中没有参数类型的重载。
此外,我们无法控制传递给函数的参数数量,例如 Javascript,使用 arguments[],因此没有参数数量的重载。
但是 PHP 并没有失控,因为它创建了: “魔术方法”,并与此一起进行了重载模拟。(有人说这个 PHP 属性命名错误)
引用: http: //php.net/manual/en/language.oop5.overloading.php
因此,如果 PHP 中不存在重载:魔术方法扮演什么角色来模拟它?
什么是神奇的方法?:
那么我们可以这样说:
注意: 应该注意的是,我们对这些魔术方法所做的就是能够修改它们以覆盖(遮蔽)它们在类中的默认函数。
让我们看一个使用魔术方法重载的示例:
使用魔术方法
__construct()
,我们重载构造函数以根据传递的参数做出反应,调用相同的方法。现在让我们使用另一种方法,例如
__call()
:__call() 有什么功能?
- 允许您捕获不存在的方法的调用。
可以重新定义此方法以满足系统的需要,或者在这种情况下提供重载。
利用这个功能,我们可以控制我们正在调用的函数并重定向到我们所指的特定函数。
让我们看一个例子:
在这个例子中,我们用不同数量的参数和不同的类型重载了我们的类。总之,可以在 PHP 中重载(模拟)。
PHP POO ESTRICTO + 1
;WAIT:那么多态性和重载不一样吗?为什么,如果是这样,你是在做多态性而不是重载吗?:
不,多态是指一组具有相同名称和相同数量的参数和类型的方法,但是定义在不同的类中,之前我们传递了不同的数据类型。
让我们看一个多态的例子:
PHP POO ESTRICTO +1;
4)我们感兴趣的神奇方法:
引用 PHP 重载文档,我们发现:
Tenemos dos puntos de interés: Ámbito Activo y Propiedades Inaccesibles
Ambito activo:
Propiedades innacesibles: Son aquellas propiedades que bien estan ocultas, o no estan definidas.
Citando lo anterior, como la sobrecarga usa los metodos magicos, y estos debes de poder acceder a propiedades innacesibles.
Se fundamenta la razón de ser métodos públicos, ya que, te deben permiten obtener valores que no están en tu ámbito, ademas de crearlos dinamicamente si NO existen, cumpliendo su rol, interactuar con métodos/propiedades innacesibles.
Veamos el ejemplo en una clase:
En este caso al usar
obtenerAtributo( )
ocambiarAtributo( )
estamos trabajando bajo atributos que están definidos dentro de la clase. Pero en el último llamado deotroAtributo
estamos definiendo un valor que no existe.Aqui entra el papel de
__set
y__get
, los cuales nos permiten trabajar bajo propiedades o métodos inexistentes:1) Si los quisiera redifinir para controlar como obtener y cambiar variables usaría:
2) Estos métodos nos permiten controlar el acceso o el cambio de propiedades.
3) No son sustitutos de los
getters/setters
, ya que, nos permiten trabajar en modos que de la forma clásica daría error, más que todo son para manejo de errores, ejemplo obteniendo/cambiando atributos que no existen, comparando con JavaScript podrían usarse como si quisiéramos evitar que se crearan objetos sinnew
.4) Podría definirse a los métodos mágicos como los
Object Watchers
de Javascript, ya que estos crean propiedades inexistentes para funcionar, pero claro esta golpea en el rendimiento del código.Entonces sabiendo cuando usarlos, ¿Cual es mas eficiente?
Ocurre un problema, son públicos y pueden acceder a mis propiedades privadas, ¿que hago?:
Como es fácil violar la encapsulación en PHP:
Veamos un ejemplo:
Tendremos dos soluciones:
1) Si trabajas con mas personas: Documentar.
2) Si no queremos documentar, para evitar usar dichos metodos, haremos lo siguiente, re-declarar los métodos mágicos:
A pesar de que estos métodos "crean" propiedades y métodos dinámicos, en ninguno de los casos funcionan como se esperaba porque los redefinimos, así podemos evitar esos posibles "fallos" de encapsulamiento.
¿Y si quiero utilizar mis propios metodos get/set?:
Sencillamente agregamos nuestros propios métodos privados:
Entonces, podemos observar que aunque si pueden generar aberturas de seguridad en el encapsulamiento de PHP, podemos proteger las propiedades, por su misma capacidad de servir (los metodos magicos) como administradores de propiedades y metodos mas adaptables a las necesidades.
PHP POO ESTRICTO + 1;
En conclusión: PHP: SI ES POO ESTRICTO.
1) Cumple con los fundamentos de la POO:
Herencia.
Abstracción.
Encapsulamiento.
2)Tiene los elementos básicos como son:
Objetos, clases y métodos.
Visibilidad privada, protegida y pública
Metodos privados y públicos
Puede emplear propiedades estáticas
Sobrecargar sus métodos.
3) Puede ademas tener polimorfismo y sobrecarga (gracias a los métodos mágicos):
4) Tiene métodos mágicos con los que:
Ampliar las capacidades de PHP como POO.
Administrar los errores en PHP, y permiten redefinir las propiedades accesoras del objeto (aumentado así la encapsulación).
Los métodos mágicos se pueden opacar (shadowing).
根据维基百科,PHP 范例是:
OOP范式的定义是:
是的,您可以在严格意义上进行 OOP,但您还必须看到,我们这些刚开始使用 OOP 的人通常会混合不同的范式。在我的项目中,我不断发现一种范式和另一种范式之间的跳跃,尤其是在小规模上。当你在 C 中工作时,一切都是命令式的并且易于阅读,所以有时你会按照这种范式用 Java 或 PHP 编写代码。但实际上如果是OO。我在 Python 中也发生了同样的事情。最初,它没有使用自己的类,它用函数来做所有事情,更不用说继承或抽象了。
随着时间的推移,你会在一种或另一种范式中获得更多的练习。在这种情况下,它并不太依赖于 PHP,而是取决于您真正了解范式的程度以及您知道如何应用它的程度。尽管在后者中会有不同的人。
更新
关于神奇的方法。在 python 中,一切都可以被覆盖并从任何地方访问。没有私人的,也没有公共的。它们存在,但它们提到了代码的格式。例如,不应从类外部访问 _VAR 变量。它们是达成的约定。这称为隐藏,它是 OOP 的特征之一。JAVA 在这个意义上是非常严格的,因为它是为团队合作而设计的。领导者、Jr 开发人员等。Python 不,它更自由。相信程序员的良好实践。然后 PHP 在这些想法中有它的家务活。无论如何,当您在 OOP 中开发项目时,您最不希望的是必须访问其他类的方法并覆盖它们。制造混乱。就个人而言,我只对 get 和 set 及其描述的结果感兴趣。访问魔术方法有一些我不想要的复杂性。