面向对象设计的下集,我们来聊静态成员static member和实例成员instance member(也有人称为非静态成员non-static,但我觉得叫实例成员会比较容易区分)。
静态成员和实例成员的区别
1、调用方式
class只能调用静态成员,实例成员需要先实例化并通过object调用,不可越雷池半步。(但是感觉php有点奇葩,class可以调用实例方法,但是会有一个Deprecated级别的错误,换java就是编译不通过了。一般其实不建议class调用实例方法,如果不得不这样做,那应该是你的程序设计有问题,对业务或者面向对象理解不足。)
2、使用场景
调用方法是从调用者角度描述的,而从被调用者方法角度来看,静态方法内部不可以直接调用实例成员,但反过来,在实例方法内部则可以直接调用静态成员。
3、内存分配
从class被加载入内存开始,class的静态成员自始至终都只有一份copy,各个线程共享这份资源。但每个object会独占一份copy,每当object被实例化的时候,都会向系统申请内存分配。
4、性能比较
一般来说,静态成员在class被引入后即可使用,实例成员还要经过实例化才能使用,性能上是静态成员快一点。
---------------------------------------------------- 分割线 -----------------------------------------------------
适用场景
静态方成员一般作为通用的工具或者配置来使用,在全局或者特定范围内使用。
而实例成员则作为个性化操作的基本单元,各个object的实例成员互不影响,是我们使用的最多的。
在实际使用中,我们经常能见到的是单例模式使用静态成员去获取(以下java版)
public class Singleton {
public static class MySingleton{
private static Singleton single = new Singleton();
}
public static Singleton getInstance(){
return MySingleton.single;
}
}
ps:不知道为什么php不支持在静态属性声明中new对象,不然就很灵活了,代码又可以写少点了。
以上是最通用的单例模式写法。这里很明显可以看出,对于静态成员的调用,如果没有外界参数输入作为参考,那么它的输出结果就会一直不变。
总结:静态成员的定义和使用应该足够抽象,与业务完全不相关,按我的理解就是,应该以过程式变成的思想去做这个事情,因为单单以静态成员去描述你的业务,表现力是肯定不够的。而实例成员的定义和使用则应该与你的业务相关,面对当前对象的状态去编码。
2018.06.21添加:
个人认为静态成员适合纯计算或者线程共享资源,数据的场景,实例成员适合需要开辟空间保存自身线程数据的场景。
网友评论