面向对象
- 面向对象,即我们以对象为核心去实现我们的目的,对象顾名思义:万物皆对象,一个人,一条狗...
- 当我们通过对象处理一些事情时,会让我们的代码清晰明了,内部高聚合,对外低耦合,即封装的思想
- 相比面向过程,面向对象会让我们的代码更加精简,更具有灵魂性,同时也提高了代码的复用性
###下面通过PHP来讲解(实例化对象) * * *
- 面向对象,有对象必然会引入类,对象是类的实例化,当我们定义一个类,比如‘人’,那么具体到男人、女人...那便是实例化对象了 - 其定义如下:
<?php
class Humen {
public $name = "熔岩巨兽"; //定义共有变量
public function eat($food){ //定义共有方法
echo $this->name."'s eating ".$food; //this是man实例化对象(伪变量)
}
}
$man = new Humen(); //通过new关键字实例化一个对象,即通过Humen类实例化出一个对象,存放到$man变量中
echo $man->name."
"; //对象通过->调用类成员(属性、方法)
$man->eat('apple');
?>
构造函数
- 当我们想要在实例化对象时,定义我们的属性和方法时,我们可以引入构造函数,这样我们便可以灵活定义属性、方法 - 其定义如下:(注:构造函数是在对象实例化时自动被调用一次,每次对象实例化都会调用一次)
<?php
class Humen {
public $name = "熔岩巨兽";
public function eat($food){
echo $this->name."'s eating ".$food;
}
function __construct($name, $sex, $age){ //__construct定义构造函数(双下划线),通过参数传入对象实例化时的属性
echo $this->name = $name."
";
echo $this->sex = $sex."
";
echo $this->age = $age."
";
}
}
$man = new Humen("剑圣", "男", "18"); //对象实例化时传入参数
echo $man->name."
";
$man->eat('apple');
?>
析构函数
- 析构函数当变量被释放后,程序运行完后会自动调用 - 由此可见,其一般用于变量释放,对象销毁等方面(注:析构函数若遇到变量释放、置空,其会被提前调用,即程序运行完毕前) - 其定义如下:
<?php
class Humen {
public $name = "熔岩巨兽";
public function eat($food){
echo $this->name."'s eating ".$food."
";
}
function __construct($name, $sex, $age){
echo $this->name = $name."
";
echo $this->sex = $sex."
";
echo $this->age = $age."
";
}
function __destruct(){ //通过__destruct来定义析构函数
echo "德玛西亚";
}
}
$man = new Humen("剑圣", "男", "18");
echo $man->name."
";
$man->eat('apple');
?>
注:-若$woman=$man
,$man=null
,那么析构函数不会被调用,因$woman
还指向Humen
的实例化对象,对象并未销毁,所以析构并未执行,要等程序结束才会被调用
-若$woman=&$man
,则会执行析构函数,因为这属于引用赋值,他俩公用一个地址,共同指向一个对象,其中一个变量销毁,那对象就销毁了,析构函数会被立即调用
继承
- 当我们定义一些类时,他们之间会有相同的属性和方法,这样定义的过程中便会重复定义 - 我们可以定义一个父类,让其拥有这些共有属性 - 让其他拥有相同属性、方法的类去继承父类 - 其定义如下
<?php
class Humen {
public $name = "熔岩巨兽";
public function eat($food){
echo $this->name."'s eating ".$food."
";
}
function __construct($name, $sex, $age){
echo $this->name = $name."
";
echo $this->sex = $sex."
";
echo $this->age = $age."
";
}
function __destruct(){
echo "德玛西亚";
}
}
class SmallHumen extends Humen{ //extends关键字定义 继承,SmallHumen子类继承了Humen父类
}
$man = new Humen("剑圣", "男", "18");
echo $man->name."
";
$man->eat('apple');
$smallHumen = new SmallHumen("德莱文", "男", "20");
echo $smallHumen->name;
?>
访问权限 public,protected,private
- public,公共属性、方法,可以被自身、子类调用,也可以在类的外部调用
<?php
class Man {
public $kl = "1";
public function eat(){
echo "I 'm Eat";
}
}
class Dog {
public $kl = "2";
public function eat(){
echo "Dog 's Eat";
echo $this->kl; //类内部调用
}
}
class SmallDog extends Dog{ //extends关键字继承
public function eat(){
echo $this->kl; //子类调用
}
}
$man = new Man();
$dog = new Dog();
$sdog = new SmallDog();
$man->eat();
$dog->eat();
echo $dog->kl; //类外部调用
echo $man->kl;
$sdog->eat();
?>
- protected, 受保护的属性、方法,自身、子类可以调用,类的外部不可以调用
<?php
class Man {
public $kl = "1";
public function eat(){
echo "I 'm Eat";
}
}
class Dog {
protected $kl = "2";
public function eat(){
echo "Dog 's Eat";
echo $this->kl; //类内部调用
}
}
class SmallDog extends Dog{ //extends关键字继承
public function eat(){
echo $this->kl; //子类调用
}
}
$man = new Man();
$dog = new Dog();
$sdog = new SmallDog();
$man->eat();
$dog->eat();
echo $dog->kl; //类外部调用,会出错
echo $man->kl;
$sdog->eat();
?>
- private,私有成员,只可以自身调用
<?php
class Man {
public $kl = "1";
public function eat(){
echo "I 'm Eat";
}
}
class Dog {
private $kl = "2";
public function eat(){
echo "Dog 's Eat";
echo $this->kl; //类内部调用
}
}
class SmallDog extends Dog{ //extends关键字继承
public function eat(){
echo $this->kl; //子类调用,会出错
}
}
$man = new Man();
$dog = new Dog();
$sdog = new SmallDog();
$man->eat();
$dog->eat();
echo $dog->kl; //类外部调用,会出错
echo $man->kl;
$sdog->eat();
?>
static关键字
- 当有多个类继承了同一个类,通过其中一个子类改变父类属性时,会同时影响其他子类,即其他子类继承的属性也会变化
- 但是由下面一段代码看,并不是这样,这不是我们所要
<?php
class Animal{
public $scale = "奔波霸";
public function changeCon ($name){
$this->scale = $name;
}
}
class Man extends Animal {
public function eat(){
}
}
class Dog extends Animal {
public function eat(){
}
}
$man = new Man();
$dog = new Dog();
$man->changeCon("霸波奔"); //改变了父类Animal里scale的值
echo $dog->scale; //对于$dog对象,scale并未改变
?>
- 引入static关键字,实现属性全局化,即一个子类改变父类的属性,其他子类继承到的属性也会变化
<?php
class Animal{
public static $scale = "奔波霸"; //通过static关键字调用静态属性,方法
public static function changeCon ($name){
self::$scale = $name; //通过selfstatic,::操作符调用静态属性,记得静态变量前加 $
}
}
class Man extends Animal { //extends关键字继承
public function eat(){
}
}
class Dog extends Animal {
public function eat(){
}
}
Man::changeCon("霸波奔"); //通过类和操作符::,直接调用静态方法(继承了父类的changeCon方法)
echo Dog::$scale; //输出后发现其他子类继承的属性也发生了变化,由此可见static将变量全局化了
?>
方法的重写(override)
- 子类里具有与父类相同名字方法 - 参数可以不同
<?php
class Animal{
public $scale = "oop";
public function changeCon (){ //父类里的changeCon方法
echo "孙爷爷";
}
}
class Man extends Animal {
public function eat(){
}
public function changeCon (){ //与父类里相同名字的方法
echo "玉帝老儿";
}
}
class Dog extends Animal {
public function eat(){
}
}
$man = new Man();
$dog = new Dog();
$man->changeCon(); //输出后,发现子类对父类方法重写了
?>
final关键字
- 在类、方法前加上final关键字后,类不可以被继承,方法不可以被重写 - final 不可以加到属性前面
<?php
final class Animal{ //final使得子类不能继承父类的方法 may not inherit
public $scale = "oop";
final public function changeCon (){ //final使得子类不能重写父类的方法 Cannot override
echo "孙爷爷";
}
}
class Man extends Animal { //子类不可以再继承父类(final关键字的作用)
public function eat(){
}
public function changeCon (){ //与父类里相同名字的方法,这里子类对父类方法的重写会失败
echo "玉帝老儿";
}
}
class Dog extends Animal {
public function eat(){
}
}
$man = new Man();
$dog = new Dog();
$man->changeCon();
?>
数据访问
- parent:: - self::
<?php
class Animal{
public $scale = "oop";
final public function changeCon (){
echo "孙爷爷";
}
}
class Man extends Animal {
public function eat(){
parent::changeCon(); //通过parent::,访问父类的方法
self::changeCon(); //通过self::,访问子类的方法
}
public function changeCon (){
echo "玉帝老儿";
}
}
class Dog extends Animal {
public function eat(){
}
}
$man = new Man();
$dog = new Dog();
$man->eat();
?>
接口(interface)
接口的定义
- interface关键字定义接口
- implements关键字实现接口
- 接口里的方法不需要具体实现
- 类通过implements实现接口后要实现方法,方法名必须与接口里的方法名一致
- 接口不可以直接实例化,必须通过类实现,然后类再去实例化
<?php
interface ICanEat { //定义接口
public function eat(); //定义方法,不需要实现
}
class Man implements ICanEat { //实现接口
public function eat(){ //实现方法
echo "I 'm a man";
}
}
class Dog implements ICanEat { //实现接口
public function eat(){ //实现方法
echo "I 'm a dog";
}
}
$man = new Man();
$dog = new Dog();
$man->eat();
$dog->eat();
?>
判断是否属于实现接口的类的实例化对象(instanceOf)
<?php
interface ICanEat {
public function eat();
}
class Man implements ICanEat {
public function eat(){
echo "I 'm a man";
}
}
class Dog implements ICanEat {
public function eat(){
echo "I 'm a dog";
}
}
$man = new Man();
$dog = new Dog();
$man->eat();
$dog->eat();
function scale ($who){
if($who instanceOf ICanEat){ //判断是否属于实现接口的类的实例化对象
echo "true";
}else{
echo "false";
}
}
scale($man); //调用上面的scale方法
scale($dog);
?>
接口的继承
- 通过extends关键字继承
- 继承后要通过类实现自己、自己的方法、父接口的方法
<?php
interface ICanEat {
public function eat();
}
class Man implements ICanEat {
public function eat(){
echo "I 'm a man";
}
}
class Dog implements ICanEat {
public function eat(){
echo "I 'm a dog";
}
}
interface YouCanEat extends ICanEat { //继承接口
public function yEat();
}
class Women implements YouCanEat{ //实现接口
public function yEat(){ //实现自己的方法
echo "You can eat";
}
public function eat(){ //实现父接口的方法
echo "I can eat";
}
}
$man = new Man();
$dog = new Dog();
$man->eat();
$dog->eat();
?>
多态
- 类实现接口后,不同的实例化对象调用接口方法时,实现的结果不同即为多态
抽象类(abstract)
- 类里的方法是全部定义好的
- 接口里的方法是没有实现的
- 抽象类里的方法是部分实现的
- 对于相同的方法定义好、实现好,便于调用;不同的方法定义抽象方法,具体到某一个子类再去具体实现
<?php
abstract class Animal{ //abstract定义抽象类
abstract public function eat(); //未定义好方法
public function breath (){ //所有子类相同的方法,在父类里统一定义,然后继承
echo "breath";
}
}
class Man extends Animal {
public function eat(){ //具体再在子类里定义,必须与抽象类里的抽象方法一致
echo "Man eat";
}
}
class Dog extends Animal {
public function eat(){
echo "Dog eat";
}
}
$man = new Man();
$dog = new Dog();
$man->eat();
$man->breath();
$dog->eat();
$dog->breath();
?>