实现方法

function关键字引入了一个方法。 方法实现PHP中常用的可见性修饰符。 在 Zephir中, 必须明确设置可见性修改器:

  1. namespace Test;
  2. class MyClass
  3. {
  4. public function myPublicMethod()
  5. {
  6. // ...
  7. }
  8. protected function myProtectedMethod()
  9. {
  10. // ...
  11. }
  12. private function myPrivateMethod()
  13. {
  14. // ...
  15. }
  16. }

方法可以接收所需的和可选的参数:

  1. namespace Test;
  2. class MyClass
  3. {
  4. /**
  5. * All parameters are required
  6. */
  7. public function doSum1(a, b)
  8. {
  9. return a + b;
  10. }
  11. /**
  12. * Only 'a' is required, 'b' is optional and it has a default value
  13. */
  14. public function doSum2(a, b = 3)
  15. {
  16. return a + b;
  17. }
  18. /**
  19. * Both parameters are optional
  20. */
  21. public function doSum3(a = 1, b = 2)
  22. {
  23. return a + b;
  24. }
  25. /**
  26. * Parameters are required and their values must be integer
  27. */
  28. public function doSum4(int a, int b)
  29. {
  30. return a + b;
  31. }
  32. /**
  33. * Static typed with default values
  34. */
  35. public function doSum4(int a = 4, int b = 2)
  36. {
  37. return a + b;
  38. }
  39. }

可选参数可以为空

Zephir确保变量的值保持声明的类型不变。 这使得Zephir将 null值转换为最近的近似值:

  1. public function foo(int a = null)
  2. {
  3. echo a; // if "a" is not passed it prints 0
  4. }
  5. public function foo(boolean a = null)
  6. {
  7. echo a; // if "a" is not passed it prints false
  8. }
  9. public function foo(string a = null)
  10. {
  11. echo a; // if "a" is not passed it prints an empty string
  12. }
  13. public function foo(array a = null)
  14. {
  15. var_dump(a); // if "a" is not passed it prints an empty array
  16. }

支持可见性

  • Public: 将标记为 public的方法导出到PHP扩展; 这意味着公共方法对PHP代码和扩展本身都是可见的。

  • Protected: 将标记为protected的方法导出到PHP扩展; 这意味着受保护的方法对PHP代码和扩展本身都是可见的。 但是,受保护的方法只能在类的作用域中调用,或者在继承它们的类中调用。

  • Private: 标记为 private 的方法不会导出到PHP扩展; 这意味着私有方法只对实现它们的类可见。

支持修改器

  • static: 使用此修饰符的方法只能在静态上下文(来自类,而不是对象) 中调用。

  • final: 如果方法具有此修饰符, 则无法对其进行覆盖.

  • deprecated: 被标记为deprecated的方法在被调用时抛出一个E_DEPRECATED错误。

Getter / Setter 快捷方式

和C#一样,在Zephir中可以使用get/set/toString快捷方式。 该特性允许您轻松编写属性的setter和getter,而无需显式地实现这些方法。

例如,如果没有快捷方式,我们需要如下代码:

  1. namespace Test;
  2. class MyClass
  3. {
  4. protected myProperty;
  5. protected someProperty = 10;
  6. public function setMyProperty(myProperty)
  7. {
  8. let this->myProperty = myProperty;
  9. }
  10. public function getMyProperty()
  11. {
  12. return this->myProperty;
  13. }
  14. public function setSomeProperty(someProperty)
  15. {
  16. let this->someProperty = someProperty;
  17. }
  18. public function getSomeProperty()
  19. {
  20. return this->someProperty;
  21. }
  22. public function __toString()
  23. {
  24. return this->myProperty;
  25. }
  26. }

您可以使用以下快捷方式编写相同的代码:

  1. namespace App;
  2. class MyClass
  3. {
  4. protected myProperty {
  5. set, get, toString
  6. };
  7. protected someProperty = 10 {
  8. set, get
  9. };
  10. }

在编译代码时,这些方法作为实际方法导出,但您不必手动编写它们。

返回类型提示

类和接口中的方法可以有“返回类型提示”。 这些将为编译器提供有用的额外信息,以告知您应用程序中的错误。 请考虑下面的示例:

  1. namespace App;
  2. class MyClass
  3. {
  4. public function getSomeData() -> string
  5. {
  6. // 这会引发编译器异常
  7. // 因为返回的值(布尔值)不匹配
  8. // 预期返回的类型字符串
  9. return false;
  10. }
  11. public function getSomeOther() -> <App\MyInterface>
  12. {
  13. // 这会引发编译器异常
  14. // 如果返回的对象没有实现
  15. // 期望的接口App\MyInterface
  16. return new App\MyObject;
  17. }
  18. public function process()
  19. {
  20. var myObject;
  21. // 类型提示会告诉编译器这一点
  22. // myObject是一个类的实例
  23. // 实现应用程序\MyInterface
  24. let myObject = this->getSomeOther();
  25. // 编译器会检查App\MyInterface是否正确
  26. // 实现一个名为“someMethod”的方法
  27. echo myObject->someMethod();
  28. }
  29. }

一个方法可以有多个返回类型。 在定义多个类型时,必须使用操作符 |来分隔这些类型。

  1. namespace App;
  2. class MyClass
  3. {
  4. public function getSomeData(a) -> string | bool
  5. {
  6. if a == false {
  7. return false;
  8. }
  9. return "error";
  10. }
  11. }

返回类型: Void

方法也可以标记为 void。 这意味着不允许方法返回任何数据:

  1. public function setConnection(connection) -> void
  2. {
  3. let this->_connection = connection;
  4. }

为什么这是有用的? 因为编译器可以检测程序是否期望从这些方法返回值,并产生一个编译器异常:

  1. let myDb = db->setConnection(connection); // 这将产生一个异常
  2. myDb->execute("SELECT * FROM robots");

严格/灵活的参数的数据类型

在 Zephir中, 可以指定方法的每个参数的数据类型。 默认情况下, 这些数据类型是灵活的。这意味着, 如果传递了具有错误 (但兼容) 数据类型的值, 则 Zephir 将尝试以透明方式将其转换为预期的数据类型:

  1. public function filterText(string text, boolean escape=false)
  2. {
  3. //...
  4. }

上述方法将适用于以下调用:

  1. <?php
  2. $o->filterText(1111, 1); // OK
  3. $o->filterText("some text", null); // OK
  4. $o->filterText(null, true); // OK
  5. $o->filterText("some text", true); // OK
  6. $o->filterText(array(1, 2, 3), true); // FAIL

但是, 传递错误的类型通常会导致错误。 不正确地使用特定的 api 会产生意外的结果。 通过使用严格的数据类型设置参数, 可以禁止自动转换:

  1. public function filterText(string! text, boolean escape=false)
  2. {
  3. //...
  4. }

现在,由于传递的数据类型无效,大多数类型错误的调用都会导致异常:

  1. <?php
  2. $o->filterText(1111, 1); // FAIL
  3. $o->filterText("some text", null); // OK
  4. $o->filterText(null, true); // FAIL
  5. $o->filterText("some text", true); // OK
  6. $o->filterText(array(1, 2, 3), true); // FAIL

通过指定严格的参数和灵活的参数,开发人员可以设置他/她真正想要的特定行为。

只读参数

使用关键字const,您可以将参数标记为只读,这有助于尊重const-correctness。 属性中不能修改标有此属性的参数 方法:

  1. namespace App;
  2. class MyClass
  3. {
  4. // "a" is read-only
  5. public function getSomeData(const string a)
  6. {
  7. // this will throw a compiler exception
  8. let a = "hello";
  9. }
  10. }

当一个参数被声明为只读时,编译器可以做出安全的假设,并对这些变量进行进一步的优化。