Home > Backend Development > PHP Tutorial > php object-oriented programming (2), php object-oriented programming_PHP tutorial

php object-oriented programming (2), php object-oriented programming_PHP tutorial

WBOY
Release: 2016-07-12 08:58:45
Original
1045 people have browsed it

php object-oriented programming (2), php object-oriented programming

Now let’s take a look at an object-oriented encapsulation issue

Encapsulation: In my understanding, it can be understood as a USB disk. We use the interface of the USB disk to interact with the computer, but we cannot see the structure inside. This feature can be called encapsulation

Benefits: Using this feature, we can maximize the quality of the code. We only need to reference the interface in other codes without having to write it every time, which improves the quality of the code and reduces the difficulty of troubleshooting bugs

Now let’s think about a problem: every personal computer has a password, and you don’t want others to log in at will and copy and paste it into your computer. Also, for objects like people, the attributes of height and age can only be increased by oneself, and cannot be assigned values ​​arbitrarily by others, etc.

We use the private keyword to encapsulate the code

private $name;	// 把人的姓名使用private关键字进行封装
private $sex;	// 把人的性别使用private关键字进行封装
private $age;	// 把人的年龄使用private关键字进行封装
private function run(){……} // 把人的走路方法使用private关键字进行封装
Copy after login

Note: As long as there are other keywords in front of the member attributes, then var

must be removed
<?php
class Person
{
	// 下面是人的成员属性
	private $name;		// 人的名子,被private封装上了
	private $sex;		// 人的性别, 被private封装上了
	private $age;		// 人的年龄, 被private封装上了

	// 这个人可以说话的方法
	function say()
	{
		echo "我的名子叫:" . $this->name . " 性别:" . $this->sex . " 我的年龄是:" . $this->age;
	}

	// 这个人可以走路的方法, 被private封装上了
	private function run()
	{
		echo "这个人在走路";
	}
}

// 实例化一个人的实例对象
$p1 = new Person();

// 试图去给私有的属性赋值, 结果会发生错误
$p1->name = "张三";
$p1->sex = "男";
$p1->age = 20;

// 试图去打印私有的属性, 结果会发生错误
echo $p1->name;
echo $p1->sex;
echo $p1->age;

// 试图去打印私有的成员方法, 结果会发生错误
$p1->run();
?>
Copy after login

 

The output result is:

Fatal error: Cannot access private property Person::$name<br />Fatal error: Cannot access private property Person::$sex<br />Fatal error: Cannot access private property Person::$age<br />Fatal error: Cannot access private property Person::$name<br />Fatal error: Call to private method Person::run() from context ' '
Copy after login
<span>没有加任何访问控制,默认的是public的,任何地方都可以访问。</span>
Copy after login

// 这个人可以说话的方法, 说出自己的私有属性,在这里也可以访问私有方法
function say()
{
	echo "我的名子叫:" . $this->name . " 性别:" . $this->sex . " 我的年龄是:" . $this->age;

	// 在这里也可以访问私有方法
	//$this->run();
}
Copy after login

Because the member method say() is public, we can call the say() method outside the class. Change the above code:

<?php
class Person
{
	// 下面是人的成员属性
	private $name;	//人的名子,被private封装上了
	private $sex;	//人的性别, 被private封装上了
	private $age;	//人的年龄, 被private封装上了

	// 定义一个构造方法参数为私有的属性姓名$name、性别$sex和年龄$age进行赋值
	function __construct($name, $sex, $age)
	{
		// 通过构造方法传进来的$name给私有成员属性$this->name赋初使值
		$this->name = $name;

		// 通过构造方法传进来的$sex给私有成员属性$this->sex赋初使值
		$this->sex = $sex;

		// 通过构造方法传进来的$age给私有成员属性$this->age赋初使值
		$this->age = $age;
	}

	// 这个人可以说话的方法, 说出自己的私有属性,在这里也可以访问私有方法
	function say()
	{
		echo "我的名子叫:" . $this->name . " 性别:" . $this->sex . " 我的年龄是:" . $this->age;
	}
}

// 通过构造方法创建3个对象$p1、p2、$p3,分别传入三个不同的实参为姓名、性别和年龄
$p1 = new Person("张三", "男", 20);
$p2 = new Person("李四", "女", 30);
$p3 = new Person("王五", "男", 40);

// 下面访问$p1对象中的说话方法
$p1->say();

// 下面访问$p2对象中的说话方法
$p2->say();

// 下面访问$p3对象中的说话方法
$p3->say();
?>
Copy after login

 Because the constructor is the default public method (do not set the constructor to be private), If the setting is called private, it is equivalent to sealing the only interface in the USB disk, and we cannot Access this class

In the above example we can see that private members can only be used inside the class and cannot be directly accessed by outside the class. However, sometimes we need to assign and read private attributes. To access, we need to provide some accessible interfaces to the outside of the class.

prvate $age; // 私有的属性年龄
function setAge($age) // 为外部提供一个公有设置年龄的方法 
{
	if ($age<0 || $age>130) // 在给属性赋值的时候,为了避免非法值设置给属性
	return;
	$this->age = $age;
}

function getAge() // 为外部提供一个公有获取年龄的方法 
{
	return($this->age);
}
Copy after login

Next we need to understand the application of the four methods __set, __get, __isset, and __unset

After the above explanation, you may have questions. So how do we operate private classes? ? ? ? ?

__set setting: __get

<?php
//__get()方法用来获取私有属性
function __get($property_name)
{
	if (isset($this->$property_name))
	{
		return ($this->$property_name);
	}
	else
	{
		return (NULL);
	}
}

//__set()方法用来设置私有属性
function __set($property_name, $value)
{
	$this->$property_name = $value;
}
Copy after login

A complete example:

<?php
class Person
{
	// 下面是人的成员属性, 都是封装的私有成员
	private $name;		//人的名子
	private $sex;		//人的性别
	private $age;		//人的年龄

	//__get()方法用来获取私有属性
	function __get($property_name)
	{
		echo "在直接获取私有属性值的时候,自动调用了这个__get()方法<br />";
		if (isset($this->$property_name))
		{
			return ($this->$property_name);
		}
		else
		{
			return NULL;
		}
	}

	//__set()方法用来设置私有属性
	function __set($property_name, $value)
	{
		echo "在直接设置私有属性值的时候,自动调用了这个__set()方法为私有属性赋值<br />";
		$this->$property_name = $value;
	}
}

$p1 = new Person();

// 直接为私有属性赋值的操作, 会自动调用__set()方法进行赋值
$p1->name = "张三";
$p1->sex = "男";
$p1->age = 20;

// 直接获取私有属性的值, 会自动调用__get()方法,返回成员属性的值
echo "姓名:" . $p1->name . "<br />";
echo "性别:" . $p1->sex . "<br />";
echo "年龄:" . $p1->age . "<br />";
?>
Copy after login

 

Program execution result:

在直接设置私有属性值的时候,自动调用了这个__set()方法为私有属性赋值<br />在直接设置私有属性值的时候,自动调用了这个__set()方法为私有属性赋值<br />在直接设置私有属性值的时候,自动调用了这个__set()方法为私有属性赋值<br />在直接获取私有属性值的时候,自动调用了这个__get()方法<br />姓名:张三<br />在直接获取私有属性值的时候,自动调用了这个__get()方法<br />性别:男<br />在直接获取私有属性值的时候,自动调用了这个__get()方法<br />年龄:20
Copy after login

If the above code does not add the __get() and __set() methods, the program will go wrong, because private members cannot be operated outside the class, and the above code automatically calls __get() and __set () method to help us directly access the encapsulated private members.

If you use the "isset()" function outside an object to determine whether the members inside the object are set, can you use it? There are two situations. If the members in the object are public, we can use this function to measure the member attributes. If they are private member attributes, this function will not work. The reason is that the private ones are encapsulated and are not exposed externally. Invisible. So we can't use the "isset()" function outside the object to determine whether the private member attributes have been set? Yes, you just need to add a "__isset()" method to the class. When the "isset()" function is used outside the class to determine whether the private members in the object are set, it will be automatically called inside the class. The "__isset()" method helps us complete such operations, and the "__isset()" method can also be made private. You can just add the following code to the class:

private function __isset($nm)
{
	echo "当在类外部使用isset()函数测定私有成员$nm时,自动调用<br />";

	return isset($this->$nm);
}
Copy after login

Complete example

<?php
class Person
{
	// 下面是人的成员属性
	private $name;		//人的名子
	private $sex;		//人的性别
	private $age;		//人的年龄

	// __get()方法用来获取私有属性
	private function __get($property_name)
	{
		if (isset($this->$property_name))
		{
			return ($this->$property_name);
		}
		else
		{
			return NULL;
		}
	}

	// __set()方法用来设置私有属性
	private function __set($property_name, $value)
	{
		$this->$property_name = $value;
	}

	// __isset()方法
	private function __isset($nm)
	{
		echo "isset()函数测定私有成员时,自动调用<br />";
		return isset($this->$nm);
	}

	//__unset()方法
	private function __unset($nm)
	{
		echo "当在类外部使用unset()函数来删除私有成员时自动调用的<br />";
		unset($this->$nm);
	}
}

$p1 = new Person();
$p1->name = "this is a person name";

// 在使用isset()函数测定私有成员时,自动调用__isset()方法帮我们完成,返回结果为true
echo var_dump(isset($p1->name)) . "<br >";
echo $p1->name . "<br />";

// 在使用unset()函数删除私有成员时,自动调用__unset()方法帮我们完成,删除name私有属性
unset($p1->name);

// 已经被删除了,所这行不会有输出
echo $p1->name;
?>
Copy after login

 

The output result is:

isset()函数测定私有成员时,自动调用<br />boolean true<br />this is a person name<br />当在类外部使用unset()函数来删除私有成员时自动调用的<br />isset()函数测定私有成员时,自动调用
Copy after login

What we are going to learn about next is inherited knowledge

The following is the human code

// 定义一个&ldquo;人&rdquo;类做为父类
class Person
{
	// 下面是人的成员属性
	var $name;	//人的名子
	var $sex;	//人的性别
	var $age;	//人的年龄

	// 定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值
	function __construct($name, $sex, $age) 
	{
		$this->name = $name;
		$this->sex = $sex;
		$this->age = $age;
	}

	// 这个人可以说话的方法, 说出自己的属性
	function say() 
	{
		echo "我的名子叫:" . $this->name . " 性别:" . $this->sex . " 我的年龄是:" . $this->age;
	}
}
Copy after login

The following is the code for the student class

class Student
{
	// 下面是人的成员属性
	var $name;		// 人的名字
	var $sex;		// 人的性别
	var $age;		// 人的年龄
	var $school;	// 学生所在学校的属性

	// 定义一个构造方法参数为属性姓名$name、性别$sex 和年龄$age 进行赋值
	function __construct($name = "", $sex = "", $age = "", $school = "")
	{
		$this->name = $name;
		$this->sex = $sex;
		$this->age = $age;
		$this->school = $school;
	}

	// 这个人可以说话的方法, 说出自己的属性
	function say() 
	{
		echo "我的名字叫:" . $this->name . " 性别:" . $this->sex . " 我的年龄是:" . $this->age . "<br />";
	}

	// 这个学生学习的方法
	function study() 
	{
		echo "我的名字叫:" . $this->name . " 我正在" . $this->school . "学习<br />";
	}
}
Copy after login

Simplify the student class

class Student extends Person
{
	var $school;	// 学生所在学校的属性

	// 这个学生学习的方法
	function study()
	{
		echo "我的名字叫:" . $this->name . " 我正在" . $this->school . "学习<br />";
	}
}
Copy after login

Now what we have to consider is the issue of overloading

At this time, you may have doubts that PHP cannot be overloaded, because PHP is a language. Overloading in the traditional sense means that there are multiple methods with the same method name, but with different numbers. parameters, we use different parameters to call different interfaces

What I call overloading is an override of the parent class by a subclass

<?
// 定义一个"人"类做为父类
class Person
{
	// 下面是人的成员属性
	var $name;		// 人的名子
	var $sex;		// 人的性别
	var $age;		// 人的年龄

	// 定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值
	function __construct($name, $sex, $age)
	{
		$this->name = $name;
		$this->sex = $sex;
		$this->age = $age;
	}

	// 这个人可以说话的方法, 说出自己的属性
	function say()
	{
		echo "我的名子叫:" . $this->name . " 性别:" . $this->sex . " 我的年龄是:" . $this->age;
	}
}

class Student extends Person
{
	var $school; // 学生所在学校的属性

	// 这个学生学习的方法
	function study()
	{
		echo "我的名子叫:" . $this->name . " 我正在" . $this->school . " 学习";
	}

	// 这个学性可以说话的方法, 说出自己所有的属性,覆盖了父类的同名方法
	function say()
	{
		echo "我的名子叫:" . $this->name . " 性别:" . $this->sex . " 我的年龄是:" . $this->age . " 我在" . $this->school . "上学";
	}
}
?>
Copy after login

This can be achieved. The key points of this method in the final analysis are:

1. Subclasses must inherit from the parent class

2. The method name of the subclass must be the same as the method name of the parent class

At this time we may find that if there are 1000 lines of code in this method, it will be very inconvenient to implement

At this time, we use the "parent::method name" method to call the overridden method in the parent class;

class Student extends Person
{
	var $school;	// 学生所在学校的属性

	// 这个学生学习的方法
	function study() 
	{
		echo "我的名子叫:" . $this->name . " 我正在" . $this->school . "学习";
	}

	// 这个学性可以说话的方法, 说出自己所有的属性,覆盖了父类的同名方法
	function say() 
	{

		// 使用父类的"类名::"来调用父类中被覆盖的方法;
		// Person::say();

		// 或者使用"parent::"的方试来调用父类中被覆盖的方法;
		parent::say();

		// 加上一点自己的功能
		echo "我的年龄是:" . $this->age . " 我在" . $this->school . "上学";
	}
}
Copy after login

The difference between public, private and protected

<?php
/**
 * Define MyClass
 */
class MyClass
{
	// Contructors must be public
	public function __construct() { }

	// Declare a public method
	public function MyPublic() { }

	// Declare a protected method
	protected function MyProtected() { }

	// Declare a private method
	private function MyPrivate() { }

	// This is public
	function Foo()
	{
		$this->MyPublic();
		$this->MyProtected();
		$this->MyPrivate();
	}
}

$myclass = new MyClass;
$myclass->MyPublic();		// Works
$myclass->MyProtected();	// Fatal Error
$myclass->MyPrivate();		// Fatal Error
$myclass->Foo();			// Public, Protected and Private work

/**
 * Define MyClass2
 */
class MyClass2 extends MyClass
{
	// This is public
	function Foo2()
	{
		$this->MyPublic();
		$this->MyProtected();
		$this->MyPrivate();		// Fatal Error
	}
}

$myclass2 = new MyClass2;
$myclass2->MyPublic();	// Works
$myclass2->Foo2();		// Public and Protected work, not Private
?>
Copy after login

From the above code we can summarize as follows

public: direct external access

protected 间接的外部访问 像U盘和电脑一样 访问需要一个接口 而那个接口就是需要一个子类 (子类继承了父类的protected)

private 不能通过外部访问

既然谈到继承的问题 如果我们想要一个类不被继承那么我们可以用final 去进行定义(只能定义类和方法,不能定义成员属性)

1.final 标记的类不能被继承

2.final标记的方法不能被子类覆盖

<?php
final class Person
{
	function say()
	{

	}
}

class Student extends Person
{
	function say() 
	{

	}
}
?>
Copy after login

  

会出现下面错误:

Fatal error: Class Student may not inherit from final class (Person)
Copy after login
<?php
class Person
{
	final function say() 
	{

	}

}

class Student extends Person
{
	function say() 
	{

	}
}
?>
Copy after login

  理解static 和const的关键关键字的使用(self:)

static 字面上的意思就是静态的意思 现在你可能会问静态使用静态有什么好处?使用静态的好处是:如果示例话成千上万“人”的对象,里面都有一个共有的属性比如国籍“中国”,那么我们可以建国籍这个属性设置为静态,在内存在开辟出一个位置,实例化的过程中成千上万的人都会访问内存中这个位置

static成员能够限制外部的访问,因为static的成员是属于类的,是不属于任何对象实例,是在类第一次被加载的时候分配的空间,其他类是无法访问的,只对类的实例共享,能一定程度对类该成员形成保护;

这一点有点像网站中的全局变量

<?
class Person
{
	// 下面是人的静态成员属性
	public static $myCountry = "中国";

	// var $name; //人的名子

	// 这是人的静态成员方法
	public static function say()
	{
		echo "我是中国人";
	}
}

// 输出静态属性
echo Person::$myCountry;

// 访问静态方法
Person::say();

// 重新给静态属性赋值
Person::$myCountry = "美国";
echo Person::$myCountry;
?>
Copy after login

  结果是:

中国我是中国人美国

也可以这么写

<?php
class MyClass
{
	// 定义一个常量constant
	const constant = 'constant value';

	function showConstant()
	{
		echo self::constant . " "; // 使用self访问,不要加&ldquo;$&rdquo;
	}
}

echo MyClass::constant . " "; // 使用类名来访问,也不加&ldquo;$&rdquo;

$class = new MyClass();
$class->showConstant();
// echo $class::constant; // 是不允许的
?>
Copy after login
Copy after login

  用“const”修饰的成员属性的访问方式和“static”修饰的成员访问的方式差不多,也是使用“类名”,在方法里面使用“self”关键字。但是不用使用“$”符号,也不能使用对象来访问。

<?php
class MyClass
{
	// 定义一个常量constant
	const constant = 'constant value';

	function showConstant()
	{
		echo self::constant . " "; // 使用self访问,不要加&ldquo;$&rdquo;
	}
}

echo MyClass::constant . " "; // 使用类名来访问,也不加&ldquo;$&rdquo;

$class = new MyClass();
$class->showConstant();
// echo $class::constant; // 是不允许的
?>
Copy after login
Copy after login

  

 

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/1101501.htmlTechArticlephp面向对象编程(二),php面向对象编程 现在我们来了解一下面向对象的一个封装性的问题 封装性:在我的理解里面 可以理解为一个u盘 我们...
Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template