原文:Zephir类和对象 #类和对象 Zephir可以优化面向对象编程,经过使用Zephir可以让你把方法和类写入到PHP扩展中,从而避免常见的运行致命错误和警告,取而代之的是编译错误。 ##类 每个Zephir文件必须实现一个且只能是一个类或者接口。Zephir的类接口跟PHP的类结构很是类似。php
namespace Test; /** * This is a sample class */ class MyClass { }
##类定义 如下类的限定是被容许的: ###Final:这个类不容许被继承html
namespace Test; /** * This class cannot be extended by another class */ final class MyClass { }
###Abstract:该类禁止被实例化编程
namespace Test; /** * This class cannot be instantiated */ abstract class MyClass { }
##编写方法 同PHP中同样,使用function关键字来定义类的方法,能够经过private、public、protected来定义方法的访问权限。app
namespace Test; class MyClass { public function myPublicMethod() { // ... } protected function myProtectedMethod() { // ... } private function myPrivateMethod() { // ... } }
方法中能够接受必选参数和可选参数,能够设定参数的默认值来实现可选参数ide
namespace Test; class MyClass { /** * All parameters are required */ public function doSum1(a, b) { return a + b; } /** * Only 'a' is required, 'b' is optional and it has a default value */ public function doSum2(a, b = 3) { return a + b; } /** * Both parameters are optional */ public function doSum3(a = 1, b = 2) { return a + b; } /** * Parameters are required and their values must be integer */ public function doSum4(int a, int b) { return a + b; } /** * Static typed with default values */ public function doSum4(int a = 4, int b = 2) { return a + b; } }
##可选的null参数 Zephir确保方法参数会被赋值,经过null默认值会在运行时转化到目标类型。如:null转化到int时为0,转换到boolean时是false,转化到string时是空字符串oop
public function foo(int a = null) { echo a; // if "a" is not passed it prints 0 } public function foo(boolean a = null) { echo a; // if "a" is not passed it prints false } public function foo(string a = null) { echo a; // if "a" is not passed it prints an empty string } public function foo(array a = null) { var_dump(a); // if "a" is not passed it prints an empty array }
##支持的权限控制修饰符优化
namespace Test; class MyClass { protected myProperty; protected someProperty = 10; public function setMyProperty(myProperty) { this->myProperty = myProperty; } public function getMyProperty() { return this->myProperty; } public function setSomeProperty(someProperty) { this->someProperty = someProperty; } public function getSomeProperty() { return this->someProperty; } public function __toString() { return this->myProperty; } }
你也能够经过如下代码实现相同功能ui
namespace App; class MyClass { protected myProperty { set, get, toString }; protected someProperty = 10 { set, get }; }
当编译器在编译生成时会自动生成相关属性的设置和get方法,可是你不用一个一个的去编写。下降编写难度。 #返回类型的声明 方法和接口能够声明返回类型,以下:this
namespace App; class MyClass { public function getSomeData() -> string { // this will throw a compiler exception // since the returned value (boolean) does not match // the expected returned type string return false; } public function getSomeOther() -> <App\MyInterface> { // this will throw a compiler exception // if the returned object does not implement // the expected interface App\MyInterface return new App\MyObject; } public function process() { var myObject; // the type-hint will tell the compiler that // myObject is an instance of a class // that implement App\MyInterface let myObject = this->getSomeOther(); // the compiler will check if App\MyInterface // implements a method called "someMethod" echo myObject->someMethod(); } }
一个方法也能够拥有多个返回类型,当定义了多个返回类型时,请使用|符号来分割各个类型spa
namespace App; class MyClass { public function getSomeData(a) -> string | bool { if a == false { return false; } return "error"; } }
##返回类型 Void 若是一个方法的返回值被声明为void,则表示该方法不容许返回任何数据。
public function setConnection(connection) -> void { let this->_connection = connection; }
设置void返回值声明后,若是有调用错误会产生编译错误而不是运行错误,避免隐性的漏洞。
let myDb = db->setConnection(connection); myDb->execute("SELECT * FROM robots"); // this will produce an exception
##静态/动态 的参数类型 在Zephir中能够特别的指定变量类型,默认状况下变量类型是动态的,若是指定了变量类型,Zephir会尝试把传入参数转化成指定的类型。
public function filterText(string text, boolean escape=false) { //... }
以上方法在执行时的结果:
<?php $o->filterText(1111, 1); // OK $o->filterText("some text", null); // OK $o->filterText(null, true); // OK $o->filterText("some text", true); // OK $o->filterText(array(1, 2, 3), true); // FAIL
如今,大多数状况下传入一个错误类型的参数会抛出一个异常
<?php $o->filterText(1111, 1); // FAIL $o->filterText("some text", null); // OK $o->filterText(null, true); // FAIL $o->filterText("some text", true); // OK $o->filterText(array(1, 2, 3), true); // FAIL
尽量的定义参数的类型有助于程序编写。 ##只读变量 经过使用const关键字声明能够标明一个变量为只读变量,这种变量将不被容许在方法中被修改。
namespace App; class MyClass { // "a" is read-only public function getSomeData(const string a) { // this will throw a compiler exception let a = "hello"; } }
当一个变量被设定为不可修改时,编译器会对这个变量作最大化的优化 ##实现类的属性 类中的变量称之为属性(properties)。Zephir类属性能够映射到PHP类中,二者对于属性的控制方法一致。
namespace App; class MyClass { // "a" is read-only public function getSomeData(const string a) { // this will throw a compiler exception let a = "hello"; } }
类中的非静态属性能够经过->来修改和读取值。
namespace Test; class MyClass { protected myProperty; public function setMyProperty(var myProperty) { let this->myProperty = myProperty; } public function getMyProperty() { return this->myProperty; } }
属性能够有默认值,可是默认值必须是静态的且不依赖与运行时的变量、参数
namespace Test; class MyClass { protected myProperty1 = null; protected myProperty2 = false; protected myProperty3 = 2.0; protected myProperty4 = 5; protected myProperty5 = "my value"; }
##更新类的属性 属性的值能够经过->引用来更新
let this->myProperty = 100;
Zephir会在编译时检查属性是否存在,若是被操做的属性不存在则会抛出以下错误:
CompilerException: Property '_optionsx' is not defined on class 'App\MyClass' in /Users/scott/utils/app/myclass.zep on line 62 this->_optionsx = options; ------------^
若是你想动态的建立一个属性并复制的话,你可使用以下的方法去实现:
let this->{"myProperty"} = 100;
你也能够经过使用变量去更新对应名称的属性值
let someProperty = "myProperty"; let this->{someProperty} = 100;
##读取类的属性 经过使用->来读取
echo this->myProperty;
当须要更新属性值时,能够动态的读取和设置值
//避免编译器检查属性是否存在,动态的建立属性 echo this->{"myProperty"} //经过变量名称来读取属性 let someProperty="mProperty"; echo this->{someProperty};
##类常量 能够定义类中的属性为常量,避免被修改。这种定义容许在php中直接使用
namespace Test; class MyClass{ const MYCONSTANT1=false; const MYCONSTANT2=1.0; }
类属性常量能够经过静态属性引用方式来读取(::)
namespace Test; class MyClass{ const MYCONSTANT1=false; public function someMethod(){ return MyClass::MYCONSTANT1; } }
##调用类的方法 调用Zephir的方法可使用和PHP类方法的调用同样的方式->
namespace Test; class MyClass{ protected function a(a,b){ return a-b; } public function b(c,d){ return this->a(c,d); } }
静态方法必须使用静态方法的操做符::
namespace Test; class MyClass { protected static function _someHiddenMethod(a, b) { return a - b; } public static function someMethod(c, d) { return self::_someHiddenMethod(c, d); } }
你也能够动态的访问某个类的方法:
namespace Test; class MyClass { protected adapter; public function setAdapter(var adapter) { let this->adapter = adapter; } public function someMethod(var methodName) { return this->adapter->{methodName}(); } }
##经过变量名来传参(高端..) 咱们先定义以下的一个类,让咱们来看看有什么神奇的使用方法
namespace Test; class Image { public function chop(width = 600, height = 400, x = 0, y = 0) { //... } }
常规状况下咱们是这样去调用方法的
i->chop(100); // width=100, height=400, x=0, y=0 i->chop(100, 50, 10, 20); // width=100, height=50, x=10, y=20
使用变量名传参的状况下你能够这样写
i->chop(width: 100); // width=100, height=400, x=0, y=0 i->chop(height: 200); // width=600, height=200, x=0, y=0 i->chop(height: 200, width: 100); // width=100, height=200, x=0, y=0 i->chop(x: 20, y: 30); // width=600, height=400, x=20, y=30
若是Zephir在编译时不知道变量顺序时,必须在运行时指定。
let i = new {someClass}(); i->chop(y:30, x: 20);
今天翻译完成...