代码解读:包的封装之Get,Set技巧

icyleaf 2 年之前

在 KO3 的 Pagination Module 的核心库 pagination class 之中涉及到了 Get,Set 使用,或许很多人不知道 Get,Set,这就要从 Java 说起:

java三大特性:封装,继承,多态
其中 get(),set() 方法就体现出了封装的特性,对类的内部数据进行隐藏。主要是对类的私有属性进行操作。

Java 程序一般将A类的属性修饰符设置为private,这是为了更好的封装数据。要想在B类里引用该属性,就可以在A类里定义修饰符为public的set,get方法以设置和获取private型的属性值

对此,请看下面摘自 pagination 中的代码:

class Kohana_Pagination {


// Current page number
protected $current_page;
 
// Total item count
protected $total_items;
 
// How many items to show per page
protected $items_per_page;
 
// Total page count
protected $total_pages;
 
// Item offset for the first item displayed on the current page
protected $current_first_item;
 
// Item offset for the last item displayed on the current page
protected $current_last_item;
 
// Previous page number; FALSE if the current page is the first one
protected $previous_page;
 
// Next page number; FALSE if the current page is the last one
protected $next_page;
 
// First page number; FALSE if the current page is the first one
protected $first_page;
 
// Last page number; FALSE if the current page is the last one
protected $last_page;


public function __get($key)
{
	return isset($this->$key) ? $this->$key : NULL;
}
 
/**
 * Updates a single config setting, and recalculates pagination if needed.
 *
 * @param   string  config key
 * @param   mixed   config value
 * @return  void
 */
public function __set($key, $value)
{
	$this->setup(array($key => $value));
}


}

大家可以看到此类使用全部都是受保护的属性变量,但是通过 __get(),__set() 方法却又可以从外部调用的时候进行赋值,使用方法:

// 控制器
$pagination = Pagination::factory();


echo '共计页面:'.$pagination->total_pages;

如何类中的属性是私有的还是受保护的通过 __get(),__set() 都可以从外部类中调用和设置其属性变量,这样就很好的做好的类的封装

如果大家不行,可以把下面的代码分别删去__get(),__set()和保留试试结果:

class User {


protected $name;
private $age;


public function __get($key)
{
	return isset($this->$key) ? $this->$key : NULL;
}
 
public function __set($key, $value)
{
	return isset($this->$key) ? ($this->$key = $value) : NULL;
}


$user = new User;
$user->name = 'icyleaf';
$user->age = 22;


echo 'User name is '.$user->name.'('.$user->age.')';


}

我一直很纠结于有没有使用__get和__set对于如此访问/设置对象成员有何区别?

$instance->member

实际上不还是对外暴露了吗?等同于将访问修饰符改为public了。

实际上,上面是一种方式,不过在PHP里,常用的是这样的:

class User {


private $data = array();


public function __set($name, $value) {
        $this->data[$name] = $value;
}


public function __get($name) {
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }
        else
        {
            return FALSE;
        }
}

@zwws

使用__set和__get,可以在用户设置或获取变量时提供一个统一的入口,对变量作进一步的处理。比如当用户设置password时,自动md5 password等等,出了问题追查起来也比较方便。

OK, 原始需求差不多可以理解为:

1. 代码的隔离控制,解耦
2. 代码的易维护性

谢谢二位,:)

发表讨论

在回复之前你需要先进行登录
记住我的登录状态 (忘记密码)