程序员面试题之Static方法与普通方法有啥不同,静态方法可以不依赖于类的实例,可以直接通过类名调用,并可以访问和修改静态属性;普通方法需要通过类的实例对象调用,并可以访问和修改实例属性。

AI:please wait…
在PHP中,静态方法(Static methods)与普通方法(Instance methods)有以下不同:

  1. 调用方式:静态方法可以通过类名直接调用,而普通方法需要通过类的实例对象调用。
    示例:

    class MyClass {
        public static function staticMethod() {
            echo "This is a static method.";
        }
        public function instanceMethod() {
            echo "This is an instance method.";
        }
    }
    
    MyClass::staticMethod(); // 调用静态方法
    $obj = new MyClass();
    $obj->instanceMethod(); // 调用普通方法
    
  2. 访问权限:静态方法可以访问和修改静态属性(Static properties),而普通方法可以访问和修改实例属性(Instance properties)。
    示例:

    class MyClass {
        public static $staticProperty = "Static Property";
        public $instanceProperty = "Instance Property";
        
        public static function staticMethod() {
            echo self::$staticProperty;
        }
        public function instanceMethod() {
            echo $this->instanceProperty;
        }
    }
    
    MyClass::staticMethod(); // 输出 "Static Property"
    $obj = new MyClass();
    $obj->instanceMethod(); // 输出 "Instance Property"
    
  3. 继承:静态方法可以被继承并覆盖(Override),而普通方法也可以被继承并覆盖。
    示例:

    class ParentClass {
        public static function staticMethod() {
            echo "This is the parent's static method.";
        }
        public function instanceMethod() {
            echo "This is the parent's instance method.";
        }
    }
    
    class ChildClass extends ParentClass {
        public static function staticMethod() {
            echo "This is the child's static method.";
        }
        public function instanceMethod() {
            echo "This is the child's instance method.";
        }
    }
    
    ParentClass::staticMethod(); // 输出 "This is the parent's static method."
    ChildClass::staticMethod(); // 输出 "This is the child's static method."
    
    $parentObj = new ParentClass();
    $parentObj->instanceMethod(); // 输出 "This is the parent's instance method."
    
    $childObj = new ChildClass();
    $childObj->instanceMethod(); // 输出 "This is the child's instance method."
    

https://www.php.net/manual/zh/language.oop5.static.php
声明类属性或方法为静态,就可以不实例化类而直接访问。
静态方法

<?php

/**
 * 静态(static)关键字
 *
 * 声明类属性或方法为静态,就可以不实例化类而直接访问。
 * 静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)
 *
 * 由于静态方法不需要通过对象即可调用,所以伪变量$this在静态方法中不可用!!
 */

class Foo
{
    public static function aStaticMethod()
    {
        // ...
        echo '静态方法调用';
    }
}

//两种静态方法的调用方式
Foo::aStaticMethod();
//$classname = 'Foo';
//$classname::aStaticMethod();

静态方法&&静态变量

<?php

/**
 * 静态(static)关键字,静态属性
 *
 * 静态属性不可以由对象通过 -> 操作符来访问。
 * 通过变量来引用一个类是可行的,但这个变量的值不能是一个保留字 (例如self,parent和 static)
 */

class Foo
{
    public static $my_static = '静态变量:foo';

    public function staticValue()
    {
        return self::$my_static;
    }
}

class Bar extends Foo
{
    public function fooStatic()
    {
        return parent::$my_static;
    }
}

print Foo::$my_static . "\n"; //直接调用静态变量


//静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)。
$foo = new Foo();
print $foo->staticValue() . "\n";   //可以访问静态方法
//print $foo->my_static . "\n";      // 会报错的,静态属性不可以由对象通过 -> 操作符来访问。

echo '<br/>';
echo '<br/>';
echo '<br/>';

$foo = new Foo();
print $foo::$my_static . "\n";
$classname = 'Foo';
print $classname::$my_static . "\n";

echo '<br/>';
echo '<br/>';
echo '<br/>';

//Bar是子类访问父类的静态变量
print Bar::$my_static . "\n";
$bar = new Bar();
print $bar->fooStatic() . "\n";

echo '<br/>';
print $bar->staticValue();

继承会覆盖

<?php

/**
 * 继承会覆盖
 */

class A
{
    static protected $test = "class a";

    public function static_test()
    {
        echo static::$test; //打印什么??    class b
        echo '<br/>';
        echo self::$test; //打印什么??      class a
    }
}

class B extends A
{
    static protected $test = "class b";
}

$obj = new B();
$obj->static_test();

静态成员由类的所有实例共享,尽管类的每个实例都存在一个非静态成员。

<?php

/**
 *  也就是说,静态成员由类的所有实例共享,尽管类的每个实例都存在一个非静态成员。
 */

class Base
{
    public $a;
    public static $b;
}

class Derived extends Base
{
    public function __construct()
    {
        $this->a = 0;
        parent::$b = 0;
    }

    public function f()
    {
        $this->a++;
        parent::$b++;
    }
}

$obj1 = new Derived();
$obj2 = new Derived();
$obj3 = new Derived();

$obj1->f();
echo $obj1->a;echo Derived::$b; //11

echo '<br/>';
echo '<br/>';

$obj2->f();
echo $obj2->a;echo Derived::$b; //12

echo '<br/>';
echo '<br/>';

$obj3->f();
echo $obj3->a;echo Derived::$b; //13

要检查类中声明的方法是否是静态的,可以使用以下代码。PHP5有一个反射类,非常有用

<?php

class base
{
    public static function test()
    {

    }

    public function test1()
    {

    }
}

try {
    $method = new ReflectionMethod('base::test');
    if ($method->isStatic()) {
        echo 'yes';
    } else {
        echo 'no';
    }
} catch (ReflectionException $e) {
    echo $e->getMessage();
}


修饰全局作用域的变量

<?php

function testStatic()
{
    static $val = 1; //修饰全局作用域的变量
    echo $val;
    $val++;
}

/**
 * 在函数执行完后,变量值仍然保存
 */
testStatic(); //echo 1
testStatic(); //echo 2
testStatic(); //echo 3

这里static的作用即类似于C里的static的作用,保证$a变量只有在add()第一次调用时才会被初始化
但需要注意的是定义static变量的时候,可以不赋初值,可以给定初值,
但是赋初值的时候不能使用表达式或者调用函数赋值,否则会报错。

    //www.kegog11.com/admin/demo/test
    public function test(){
        for($i=0;$i<5;$i++){
            static $a = 0;
            echo $a,"<br />";
            $a++;
        }
        echo $a,"<br />";
    }
    //结果集?

static变量不会存储引用(但是可以存储对象)
当static存储引用时,二次调用函数后,该变量的值并未被保存下来,
且运行上面程序会报Deprecated错误,即返回引用值赋值的用法已弃。

<?php

function get_obj_ref(){
    static $obj = null;
    echo '第一个:Ststic obj:';
    var_dump($obj);
    echo '<br/>';
    if(is_null($obj)){
        $obj = &new stdClass();
    }
    return $obj;
}
$obj = get_obj_ref();
$obj2 = get_obj_ref();

//====================================================
echo '<br/>';

function get_obj_noref(){
    static $obj = null;
    echo '第二个:Ststic obj:';
    var_dump($obj);
    echo '<br/>';
    if(is_null($obj)){
        $obj = new stdClass();
    }
    return $obj;
}
$obj = get_obj_noref();
$obj2 = get_obj_noref();

static在类中的延迟静态绑定;

/**
 * 2:static在类中的延迟静态绑定;
 *
 * 延迟静态绑定是指允许在一个静态继承的上下文中引用被调用类。
 * 延迟绑定的意思为:
 * static::不再为定义当前方法所在的类,而是实际运行时所在的类。注:它可以用于(但不限于)静态方法的调用。
 *
 * 除了简单的static延迟绑定的用法,还有一种转发调用,即使用self::,
 * parent::,static:: 以及forward_static_call()(该函数只能在方法中调用)将转发调用信息,如下:
 */

class A
{
    public static function foo()
    {
        static::who();
    }

    public static function who()
    {
        echo __CLASS__ . "\n";
    }
}

class B extends A
{
    public static function test()
    {
        A::foo();
        parent::foo();
        self::foo();
    }

    public static function who()
    {
        echo __CLASS__ . "\n";
    }
}

class C extends B
{
    public static function who()
    {
        echo __CLASS__ . "\n";
    }
}

C::test();

//这里得到的结果是A C C,显然在调用parent::foo()时,还是使用了运行时调用类。

还有一点需要注意的是:只有显示声明的static类才是从属与子类的。

<?php
/**
 * 还有一点需要注意的是:只有显示声明的static类才是从属与子类的。
 *
 * 这里得到的结果是 b b。这里B类首先调用过test()方法,调用后$var2变量已经被赋值,
 * 而C类未定义自己的$var2变量,且父类中$var2变量值已经存在,
 * 故直接使用,若在B C类中显示定义$var2变量,则结果又会有所不同。
 */

class A
{
    protected static $var1 = null;
    protected static $var2 = null;

    public static function test()
    {
        if (!static::$var2) {
            static::$var2 = static::$var1;
        }
        echo get_called_class() . '===>' . static::$var2 . '<br/>';
    }
}

class B extends A
{
    protected static $var1 = 'b';
}

class C extends A
{
    protected static $var1 = 'c';
}

B::test();
C::test();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值