类和对象的区别及联系:
① 类是抽象的,代表一类事物
② 对象是具体,是类的一个具体实例
③ 类是对象的模板, 对象是类的一个个体实例
【分析对象在内存中存在的形式】
【如果给一个函数传递一个对象,实际上是传递的一个地址.】
如果给函数传递的是基本数据类型( 整数、小数、布尔、字符) ,在默认的情况下是传递的值,如果希望传入地址,要加&:
function test(&$变量....){ }
在php中如果,给一个函数传递的是数组,则默认情况下是传值(拷贝了新的数组),如果希望传入地址,则应当使用:&$数组名.
函数和成员方法关系:当我们把一个函数写到某个类中,则该函数可以称成员方法。举例如下:
【构造方法——没有返回值】
$this的使用:
1. $this 本质可以理解就是这个对象的地址
2. 哪个对象使用到$this, 就是哪个对象地址
3. $this不能在类外部使用.
【构造方法的总结】
(1)一旦自定义了一个构造函数,默认的构造函数就被覆盖了,这时在创建对象的时候就要使用自定义的构造函数.
(2)一个类只能有一个构造函数.(不能重载)
【构造方法的8点说明】
①构造方法名和类名相同(php4版),php5版的构造方法——名可以和类名相同,也可以是__construct()
②构造方法没有返回值
③主要作用是完成对新对象的初始化,并不是创建对象本身。
④在创建新对象后,系统自动的调用该类的构造方法
⑤一个类有且只有一个构造方法,在php5后虽然__construct() 和类名() 可以共存,但是实际上也只能使用一个。
⑥如果没有给类自定义构造方法,则该类使用系统默认的构造方法。
⑦如果给类自定义了构造方法,则该类的默认构造方法被覆盖。
⑧构造方法的默认访问修饰符是public
【析构方法】——主要用于释放资源(比如释放数据库的链接、图片资源、销毁某个对象…)
根据上面的代码可以分析:
析构方法总结:
⑥析构方法不能传参数
【全局变量】——在程序中都可以使用的变量称为全局变量
有一群小孩在玩堆雪人,不时有新的小孩加入,请问如何知道现在共有多少人在玩?
请使用面向对象的思想,编写程序解决。
使用全局变量完成(非面向对象)
【静态变量】
静态变量与普通变量的区别:
(静态的变量的基本用法)
1.在类中定义静态变量:[访问修饰符] static $变量名;
2. 如何访问静态变量
(1)如果在类中访问,有两种方法:self::$静态变量名 , 类名::$静态变量名
(2)如果在类外访问,有一种方法:类名::$静态变量名
【静态方法】
当我们操作静态变量的时候,我们可以考虑使用静态方法,编程中经常需要使用静态方法去操作静态变量。
静态方法的特点:①静态方法只能操作静态变量,不能操作非静态变量。
②普通的成员方法,既可以操作非静态变量,也可以操作静态变量。
静态方法案例:统计所有学生交的学费。
【抽象】
思路延伸:根据不同权限判断是否可以查看工资:
思路延伸:对指定的值进行修改
注意:成员方法之间互相调用,需要使用$this->…
根据上面的思路延伸,得出如下的魔术方法,不推荐使用,不过要认识。
【继承extends】
继承:就是一个子类通过 extends 父类,把父类的 (public/protected)属性和(public/protected)方法继承下来.
继承的基本语法是:
class 类名 extends 父类名{
//在写自己需要的属性和方法.
}
继承的细节讨论:
①父类的 public 、protected 的属性和方法被继承,private 的属性和方法没有被继承.
②一个类只能继承一个父类,(直接继承).如果你希望继承多个类的属性和方法,则使用多层继承
③当创建子类对象的时候,默认情况下,不会自动调用父类的构造方法.
④如果要调用父类的构造方法或者其它方法(public/protected),可以使用类名::方法名() 或parent::方法名()[仅供了解]
⑤当一个子类的方法和父类的方法完全一样(public/protected), 我们称为方法的覆盖(方法重写).
【方法重载(overload)】
PHP5 中通过魔术方法 __call()来实现方法重载的效果:
关于重载——php5 默认情况下不直接支持方法重载,php5 使用__call魔术方法,模拟一个方法重载的效果.
补充:PHP的魔术常量:
【方法重写/方法覆盖(override)】
关于方法重写的细节讨论
1.要实现重写,要求子类的那个方法的名字和参数列表个数一摸一样,但是并不要求参数的名称一样.
2.如果子类要去调用父类的某个方法(public / protected) 则可以使用 parent::方法名(参数..) , 父类名::方法名(参数...)
3.在实现方法覆盖的时候,访问修饰符可以不一样 //但是必须满足: 子类的访问范围>=父类的访问范围
多态的体现:当子类没有覆盖父类的方法则调用的是父类的方法,当子类覆盖了父类的方法,则调用自己的方法。
【抽象类】
①如果一个类使用abstract 来修饰,则该类就是抽象类, 如果一个方法被abstract修饰,则该方法就是抽象方法
②抽象方法不能有方法体abstract public function cry(){ //…}这样是错的
③抽象类可以没有抽象方法.同时还可以有实现了的方法.
abstract public function cry();上面的这行代码可以没有。
public function cry(){echo "crying...";}也可以是实现了的方法
④ 如果一个类中,只要有抽象方法,则该类必须声明为abstract
abstract class A{ //如果这里是class A{},则会报错
abstract function test();
}
⑤如果A1类继承了一个抽象类A,则要求A1类实现从A类继承的所有抽象方法
【接口】
【接口的使用基本语法】
interface 接口名{
//属性
//方法
}
接口的方法都不能有方法体
如何去实现接口?
class 类名 implements 接口名1,接口2.{ //可以继承多个接口
}
接口它的作用就是:声明一些方法,供其它类来实现. 接口还体现编程中我们希望的效果高内聚低耦合的特点:
继承是实现接口的关系一览图:
什么情况下可以考虑使用接口?
(1)定下规范,让别的程序员来实现。
(2)当多个类,他们之间是平级的关系. 这些类都会去实现某个功能,只是实现的方式不一样.
【接口的细节】
1. 不能去实例化一个接口
interface iUsb{
}
$a=new iUsb(); (错误!!!)
2. 接口中的所有方法,都不能有方法体
3. 一个类可以去实现多个接口,语法:
class 类名 implements 接口1,接口2{
}
4. 接口中可以有属性,但是必须是常量,并且是public
interface iUsb{
const A=90; //如果是 $a=90; 就会出错
}
要取到属性:iUsb::A;
5.接口的方法是public 【默认就是public】 ,不能是 protected 和private,举例:
interface iUsb{
const A=90;
protected function test(); //会出错,这里必须是public
}
6. 一个接口不能继承其他的类,但是可以继承别的接口。一个接口可以继承多个其它的接口.当一个类去实现了某些接口,则必须把所有接口的方法都实现。
类和接口之间关系一览图:
代码说明:
7.一个类可以同时继承他的父类,而且实现接口:
class A1 extends A implements iUsb2,iUsb3{…}
继承和实现接口的比较:
(1) 可以认为实现接口是对单一继承的补充.
(2) 可以在不破坏类层级关系的前提下,对某个类功能扩展.
【final 关键字】
①如果希望某个类不被其它的类来继承(可能因为安全考虑...), 可以使用final关键字
②如果希望某个方法,比如计算个人所得税的方法,不能被子类改写,可以使用fianl 来修饰方法
③ final关键字不能去修饰属性,即 final public $name; 这样的写法没有意义。
【const关键字】
当有一个属性,不希望被修改,则使用const 做成常量(都是public的)。基本用法是:
class 类名{
const 常量名(大写)= 赋初值;
}
interface 接口名{
const 常量名(大写)= 赋初值;
}
使用方法 类名::常量名; 接口名::常量
1.常量在定义的时候需要赋初值
2.常量不能修改.
3.常量名不能有 $, 一般是大写, 默认是public
4.常量在类的内部使用 self::常量的名称类名::常量的名称,在类的外部使用类名::常量的名称.
【代码】https://github.com/rxbook/study-php-object/tree/master/code03