Npcink Blog
切换菜单

类中类外访问静态成员和普通成员 - PHP 面向对象编程(OOP)

在 php 中的访问常量和静态量的方法总结

更新于
本页目录6 节

范围解析操作符 (::)

理解

类外使用

静态成员

  • $obj::$member1;// 访问实例中的静态变量
  • ClassName::member3_visit2();// 访问 ClassName 类中的静态方法

普通成员

  • echo $obj->member1;// 访问实例中的变量
  • $obj->member2();// 访问实例中的方法

常量

  • echo $obj::member1;// 访问实例中的常量

类内使用

静态成员

  • self::$member2;// 访问类中静态变量
  • ClassName::$member2;// 访问类中静态变量(不建议使用)
  • self::member2;// 访问类中静态方法

普通成员

  • echo $this->member2;// 访问类中的变量
  • echo $this->member3();// 方法中访问其他方法

常量

  • echo self::member2;// 方法中访问常量

访问大纲

访问又分为静态成员的访问和普通成员访问

1:静态成员

  • 类内访问
self::$静态属性名
self::$类常量名

( 其实类内页可以使用类外访问的类名的访问方式,不过考虑到了后期类名的更改,self 就很方便的解决了这个问题 )

  • 类外访问
类名::$静态属性名
类名::$类常量名

2:普通成员

  • 类内访问
$this->属性名
$this->方法名
  • 类外访问
$对象名->属性名
$对象名->方法名 ($对象名 指的是实例化后的对象)

实战演示

一:静态成员属性的访问

1: 静态外部访问

<?php
class ClassName {
//必须带“$”,否则是常量
public static $member1 = '成员1';
}
$obj = new ClassName;
//注意这里的“::”
echo $obj::$member1;
?>

输出:

成员1

2:静态内部访问 (要知道,在类内部访问类成员必须定义一个方法来访问)

<?php
class ClassName {
//必须带“$”,否则是常量
public static $member2 = '成员2 <br />';
public function member2() {
echo self::$member2;
//下面这条效果与上条相同,但不推荐使用(考虑继承中。类名会变的因素)
echo ClassName::$member2;
}
}
$obj = new ClassName;
//类内访问类中静态成员
$obj->member2();
?>

输出:

成员2成员2
  • 1:类内访问类内成员首先要定义一个方法在方法内访问;
  • 2:最开始介绍到:类内其实可以使用类名的访问方式(echo ClassName::$member2;),考虑到项目后期可能会有类名更改问题,类内最好使用 self 来代替

(不过也正好证明了在类内访问其实就是使用类(名)进行指定类内的成员,讲这个是因为不同于普通成员中的类内访问方式 --$this)

二:静态成员方法的访问

1:在类外访问类内静态方法

<?php
class ClassName {
//静态方法
public static function member3() {
echo __METHOD__;//打印当前方法的方法名
}
}
//类外访问类内静态方法
ClassName::member3();
?>

输出:

ClassName::member3

在类外使用 类名::类中的方法名。 (__METHOD__ 指的是当前方法的方法名

2:在类内访问类内静态方法

<?php
class ClassName {
//静态方法
public static function member3() {
echo __METHOD__.'<br />';//打印当前方法的方法名
}
//方法访问静态方法
public function member3_visit1() {
self::member3();
}
//静态方法访问静态方法
public static function member3_visit2() {
self::member3();
}
}
$obj = new ClassName;
$obj->member3_visit1();
ClassName::member3_visit2();
?>

输出

ClassName::member3
ClassName::member3
  • 类内访问静态方法,同样需要在方法内访问,
  • 定义的方法可以使用普通方法进行访问,
  • 也可以定义一个同样是静态方法的方法来访问其他静态方法。。
  • (可能这句话有些绕,直接分析代码就行)

三:普通成员的属性访问

1:在类外访问

<?php
class ClassName {
public $member1 = '成员1 ';
}
$obj = new ClassName();
//注意这里,不是“$member1”
echo $obj->member1;
?>

输出:

成员1

这里有个重点,记得看后面

2:在类内访问

<?php
class ClassName {
public $member2 = '成员2 ';
function member2() {
echo $this->member2;
}
}
$obj = new ClassName();
$obj->member2();
?>

输出:

成员2

你可能已经发现了,为什么在最开始静态访问演示的时候,

function member2() {
echo $this->member2;
}
$obj->member2();

上面变量名都有$符号,而这里却没有。
要知道这里面 php 里面有个可变属性和可变方法。下面来演示一下。

在外面如果不带$,就是代表着取 obj 这个对象中进行访问查找 为此名字的成员。

一旦加上$,因为在类外部,就会被当做变量来找,所以就会报错。当然可以这样写 ⬇

<?php
class ClassName {
public $member1 = '成员1 ';
public $member2 = '成员2 ';
function member2() {
echo $this->member2;
}
}
$obj = new ClassName();
$member1 = 'member1';
echo $obj->$member1;
$obj->member2();
?>

输出:

成员1 成员2

(其中一个值当作另一个的名)当 obj 进行指向访问的时候 $member 就会被解析为 member

四:普通成员的方法访问

1: 类外访问

<?php
class ClassName {
public $member2 = '成员2,<br /> ';
function member2() {
echo $this->member2;
}
public function member3() {
echo __METHOD__;//打印当前方法的方法名
}
}
$obj = new ClassName();
$obj->member2();
$obj->member3();
?>

输出

成员2,
ClassName::member3

2:类内访问

<?php
class ClassName {
public function member3() {
echo __METHOD__.'<br />';//打印当前方法的方法名
}
public function member4() {
echo $this->member3();
//与上面一行代码同样的意思
$member3 = 'member3';
echo $this->$member3();
}
}
$obj = new ClassName();
$member4 = 'member4';
$obj->$member4();
?>

输出:

ClassName::member3
ClassName::member3

再次直接写了 可变的 形式,方法同样适用。

思考(这样的好处,以后比如前台页面的访问可以都给定 一个页面,页面中定义好类,类中定义好各个对象,通过页面点击传递要制定的对象名也就是方法名,然后使用可变的形式,来随时替换到变量,而调用只需要调用一次 $obj->变量名)

五:类常量的访问

首先:类常量就是 const 定义的常量。

要记住:类常量只能用 const 来定义

1:类外访问

<?php
class ClassName {
const member1='类常量1<br />';
}
$obj = new ClassName;
echo $obj::member1;
?>

输出:

类常量1

2:类内访问

<?php
class ClassName {
const member2='类常量2<br />';
public function visit() {
echo self::member2;
}
}
$obj = new ClassName;
$obj->visit();
?>

输出

类常量2

跟静态方式其实一样,但唯一的差别就是最前面中的 注释,变量名在类内声明的时候没有 $

注意:(至于可变的形式,在常量中类内或者类外访问都不可以

<?php
//以下代码采用可变方法访问常量,会报错
class ClassName {
const member1='类常量1<br />';
}
$obj = new ClassName;
//可变方法
$member1 = 'member1';
echo $obj::$member1;
?>

不过在调用方法的时候可以使用可变的形式,毕竟跟常量也没太大关系。

类与对象的内存关系

我们上面都知道,静态访问和类常量都是使用 类名来访问,而其他都是通过实例化的对象来访问。

其实:

在类内部,是分空间的,静态成员一般保存在类空间里,而像其他的 普通属性都是保存在对象的空间里(这里的对象指的是实例化的对象)

而唯一特殊的就是 成员方法,它按我们的访问方式是通过 对象来访问的,但是它并不存储在对象的空间里,相反存储在了类的空间里

我们来使用前面的代码 证明一下:

<?php
class ClassName {
public $member1 = '成员1 ';
public $member2 = '成员2,<br /> ';
function member2() {
echo $this->member2;
}
//两个成员方法的访问
public function member3() {
echo __METHOD__.'<br />';//打印当前方法的方法名
}
public function member4() {
$member3 = 'member3';
echo $this->member3();
}
}
$obj = new ClassName();
$obj->member1 = '成员5';
echo $obj->member1;
$member1 = 'member1';
echo $obj->$member1;
$obj->member2();
$obj->member3();
$member4 = 'member4';
$obj->$member4();
$obj1 = new ClassName;
echo $obj1->member1;
?>

输出

成员5成员5成员2,
ClassName::member3
ClassName::member3
成员1

可以看出 新声明的 obj1 明显没有被前面的 obj 改变的成员 5 而改变!

就算是这个特殊的成员方法虽然存在了类空间里,但是仍不会被改变。

这样的原因就是因为存储在了 实例化的对象的空间里,一个实例化中的改变不会影响其他实例化对象的改变

<?php
class ClassName {
//两个静态属性
public static $member1 = '静态成员1 <br /> ';
public static $member2 = '静态成员2 <br /> ';
//两个静态方法
public static function member3() {
echo __METHOD__.'<br />';//打印当前方法的方法名
}
public function member3_visit1() {
self::member3();
}
public static function member3_visit2() {
self::member3();
}
public function member2() {
echo ClassName::$member2;
}
}
$obj = new ClassName();
//类外访问类中静态属性
ClassName::$member1 = '11131313';
echo ClassName::$member1;
//类内访问类中静态属性
$obj->member2();
//类外访问类内静态方法
ClassName::member3();
$obj->member3_visit1();
ClassName::member3_visit2();
$obj1 = new ClassName;
echo ClassName::$member1;
?>

而在类空间中除了不能改变的,常量外的静态成员,只要被改变,其他的实例化对象同样就会被调用。如上所显示。

参考文章

  1. reactive - Vue3 composition(组合式)API

  2. var - CSS 自定义变量

  3. 图片横向排版最佳实践 - CSS 笔记