泛型基础知识
泛型就是在类或者方法定义时不指定具体类型,在使用时再确定具体要使用的类型。泛型可以增强程序的灵活性和可维护性,减少代码冗余,提高代码的复用率和稳定性。
1. 泛型的定义
我们可以用以下方式定义一个泛型类:
class GenericClass {
private $t;
public function set(T $t) {
$this->t = $t;
}
public function get() {
return $this->t;
}
}
在这个定义中,我们使用了泛型占位符T来代表待确定的具体类型,T可以代表任意类型,当我们实例化GenericClass时,可以通过尖括号<>指定具体类型,如:
$g = new GenericClass<string>();
$g->set('hello');
echo $g->get();
在这个例子中,泛型变量T被确定为string类型,$g实例化的类GenericClass也就是具备了存储字符串的能力。
2. 泛型方法
我们可以使用泛型方法来定义复杂的操作,比如对一个数组进行排序:
function sortByLength(array &$arr) {
usort($arr, function($a,$b) {
//比较两个字符串的长度
return strlen($a) - strlen($b);
});
}
在上例中,我们通过usort函数实现了按字符串长度排序的函数sortByLength,但只能用来排序字符串,如果要排序其他类型的数据,要写另外一个函数。这时候就可以使用泛型方法,将方法参数的类型拓展为T,实现对任意类型的数据排序:
function sortByLengthGeneric(array &$arr, callable $compare) {
usort($arr, function($a,$b) use ($compare) {
//使用比较函数来比较两个元素
return $compare($a,$b);
});
}
//使用sortByLengthGeneric函数进行排序
$arr = [1, 22, 333, 4, 55, 6666];
sortByLengthGeneric($arr, function($a,$b) {
return strlen((string)$a) - strlen((string)$b);
});
print_r($arr);
这样我们就实现了对于任意数据类型的排序,只需要传递一个比较函数即可。
3. 泛型接口
接口也可以使用泛型:
interface GenericInterface {
public function get(): T;
}
//实现泛型接口
class StringGetter implements GenericInterface<string> {
private $str;
public function __construct(string $str) {
$this->str = $str;
}
public function get(): string {
return $this->str;
}
}
在这个例子中,我们定义了一个泛型接口GenericInterface,约定了一个get方法,要求实现类返回指定类型的数据。我们实现了泛型接口,并取指定返回类型为string。当我们实例化StringGetter时,可以获得指定类型的数据。
总结
泛型可以让我们的程序更加灵活,增强了代码的可维护性和可读性,使用泛型能够让我们的代码更加简洁,有效减少了代码的冗余。掌握与应用泛型也必将是一个优秀的PHP开发工程师的必备技能。