实例与静态方法。静态或动态调用

时间:2018-03-31 15:31:33

标签: php oop methods static non-static

在PHP中有实例方法和静态方法(只是这两种类型)?然后我们可以静态或非静态地调用其中任何一个(名称"动态"?)?

所以我们可以:

  1. 静态调用实例方法;
  2. 非静态地调用实例方法;
  3. 静态调用静态方法;
  4. 非静态地调用静态方法(所有四个都正确吗?)
  5. 这四个代码看起来怎么样?有没有好的网站解释这个?我目前正在阅读以下网址:

    http://php.net/manual/en/language.oop5.basic.php

    ......我不理解这个:

    " $这是对调用对象的引用(通常是方法所属的对象,但如果从辅助对象的上下文中静态调用该方法,则可能是另一个对象)。"

    代码如何从次要对象静态调用方法?我的意思是,staticall调用与非静态调用,这是什么?

2 个答案:

答案 0 :(得分:1)

您不应该静态调用非静态方法。

一些例子

class foo{
    public static function bar(){
        echo __METHOD__;
    }
    public function biz(){
        echo __METHOD__;
    }
}

测试

//instance call
(new foo)->biz(); //echos  foo::biz (don't worry about the :: here, its part of __METHOD__)

//static call, statically
foo::bar() // echos  foo::bar

//call non-static statically
foo::biz() //in PHP7.1
    <b>Deprecated</b>:  Non-static method foo::biz() should not be called statically in <b>[...][...]</b> on line <b>18</b><br />

//call static non-statically
 (new foo)->bar(); // echos  foo::bar

静态非静态调用背后的想法是允许在非静态方法中使用静态属性。例如:

class foo{
    protected static $boo = "hello";

    public static function bar(){
        echo __METHOD__;
    }
    public function biz(){
        echo __METHOD__;
        echo self::$boo;
        echo static::$boo; //late static binding
    }
}

所以这很好,现在另一方面是在静态方法中调用非静态方法。

class foo{
    protected $boo = "hello";

    public static function bar(){
        echo __METHOD__;
        $this->boo; // this is a no no, because no instance exists and therefor $this does not work
    }
    public function biz(){
        echo __METHOD__;
    }
}

要指出的其他一些事项

  • 当调用静态$时,这是不可用的,它假设您将在非静态方法中使用$ this,因此静态调用它可能会导致问题。
  • 当调用非静态$时,这就存在,并且进行静态调用没有问题,因此非静态调用静态方法不是问题。即。自我和静态是无关紧要的。
  • 静态属性与类的所有实例共享
  • 父级访问的静态属性不能由子级(使用self时)更改
  • 父级访问的静态属性可以由子级更改(使用静态,后期静态绑定时)

现在,如果你想要确切答案:

  1. 静态调用实例方法;
    • 你可以,但不应该因为$这不存在
  2. 非静态调用实例方法;
    • 这是正常的
  3. 静态调用静态方法;
    • 这也很正常
  4. 非静态地调用静态方法(所有四个都正确吗?)
    • 无论范围如何,确保静态可用
  5. 我们可以使用上面的类

    来举例说明
    class foo{
        public static function bar(){
            echo __METHOD__;
        }
        public function biz(){
            echo __METHOD__;
            print_r($this);
        }
    }
    //call non-static statically
    foo::biz();
    

    结果(PHP7 +)

     <br />
     <b>Deprecated</b>:  Non-static method foo::biz() should not be called statically in <b>[...][...]</b> on line <b>15</b><br />
    
    foo::biz //output of __METHOD__
    
    <br />
     <b>Fatal error</b>:  Uncaught Error: Using $this when not in object context in [...][...]:11
     Stack trace:
     #0 [...][...](15): foo::biz()
     #1 {main}
     thrown in <b>[...][...]</b> on line <b>11</b><br />
    

    如您所见,我们在尝试访问$this

    时收到致命错误

    结果(PHP5的东西)

    <br />
    <b>Strict Standards</b>:  Non-static method foo::biz() should not be called statically in <b>[...][...]</b> on line <b>16</b><br />
    foo::biz<br />
    <b>Notice</b>:  Undefined variable: this in <b>[...][...]</b> on line  <b>11</b><br />
    

    现在我们没有在PHP7(某事)中得到致命错误,乍一看这似乎没问题。就像它说这样运行一样好。但是,如果你仔细观察Undefined variable: this,这实际上比致命错误更糟,因为现在你的班级会产生意想不到的结果。

    如果我们称之为正常:

    (new foo)->biz();
    

    结果

    foo::biz //output of __METHOD__
    foo Object //output of $this
    (
    )
    

    所以我想在self vs static上给你一个简单的例子,这可能会令人困惑。

    class foo{
        protected static $test = 'true';
    
        public function boo(){
            echo self::$test."\n";
            echo static::$test."\n";
        }
    }
    
    
    class bar extends foo{
        protected static $test = 'false';
    
        public function biz(){
            echo self::$test."\n";
            echo static::$test."\n";
        }
    }
    
    
    $B = new bar;
    
    $B->boo();
    echo "--------------\n";
    $B->biz();
    

    结果

    -------------- defined in parent ----
    true //call boo() self
    false //call boo() static
    -------------- defined in child ----
    false //call biz() self
    false //call biz() static
    

    当您使用static时,它被称为后期静态绑定。这意味着静态值是迟到的。那真正意味着什么呢?这意味着该值在运行时解析,而不是在PHP解析类时解析。

    • barfoo的孩子。
    • 我们实例化了孩子foo,我们所有的电话都通过了foo
    • 方法boo仅存在于父级中,即。它没有被儿童方法覆盖。
    • foo的值是&#39; true&#39;
    • bar的值是&#39; false&#39;

    对于第一个,我们得到foo的值,因为我们使用的是自我,所以它只知道自己。

    对于第二个,我们得到bar的值,因为我们使用静态,它的后期绑定并且可以使用在其中设置的子值。声明属性$test。因此,尽管父母对孩子一无所知(典型),但它可以使用它的价值,因为它在运行时得到了解决。

    对于第三个,我们得到bar的值,因为它知道自己,并且该方法本身已定义。 foo对这种方法一无所知,即使它确实会被孩子的减速所覆盖。

    对于第四个,我们再次获得bar的值这是因为即使使用后期静态绑定,我们也会提取相同的数据,bar的值,因为bar是类我们实例化了,所以在运行时,在属性中定义的值是值。

    因此,在最后2中,值是相同的,因为自身和静态解析相同的信息,无论它们何时被调用。

    这可能非常令人困惑,所以希望它有意义。另外,正如我已经表明的那样,不要害怕做一些像这样的简单课程并测试你得到的价值观。这就是我学习的方式。

    更新

    你提到使用静态调用被认为是坏的。

    我认为大部分都来自依赖性问题。这是类的名称和代码之间的紧密耦合。使用实例时,将其分配给变量,并在调用new时使用名称1次。调用static时,每次都使用类名。这导致的问题是您决定重命名该类。对于实例调用,您只需要替换调用new的名称,使用static,您必须在任何地方替换它。

    例如考虑这一点。

    $foo = new foo;
    $foo->one();
    $foo->two();
    //say you inject this into another class
    $foo->three();
    

    并将其与此进行比较。

    foo::one();
    foo::two();
    //say you inject this into another class
    foo::three();
    

    现在说你改变了班级名称。对于第一个,你必须在一个地方更换它。对于第二个,您必须将它替换为您使用它的地方。你可以通过使用字符串变量来解决这个问题。

    $class = 'foo';
    $class::one();
    $class::two();
    //say you inject this into another class
    $class::three();
    

    但是有了这个,你也会遇到很多麻烦,因为大多数IDE都无法解决这个问题而且会自动完成。

    此外,如果您在其他类的输入上键入提示

     class other{ 
        public method inject(foo $foo){}
     }
    

    这对静态类没有用,因为你传入一个字符串然后(类名)。

    命名空间可能是个问题。通过实例化,您只需要将use语句放在您实例化类的文件中。对于静态,您必须将它放在任何地方,或者在每次调用中包含它。

     \mystuff\foo::bar();
    
     $foo = '\\mystuff\\foo';
     $foo::bar();
    

    我确信还有其他原因,但这些是我的主要原因。

答案 1 :(得分:0)

让我们看看以下代码:

@objc

它会显示<?php class A { public $property = "property A"; public function testA() { echo "class A "; echo $this->property; } } class B { public $property = "property B"; public function testB() { A::testA(); } } $b = new B; $b->testB();

您正在使用class A property BB课程中A访问某个媒体资源。 这不适用于PHP 7+,您将在PHP 5.6上收到以下警告:

$this

它“有效”,但你不应该从静态上下文中调用非静态方法。