GridView1_RowDeleting () не быть названным?

Чтобы по-настоящему понять, о чем мы говорим, когда говорим о self против $this, нам нужно на самом деле разобраться в том, что происходит на концептуальном и практическом уровне. Я действительно не чувствую, что какой-либо из ответов делает это надлежащим образом, поэтому вот моя попытка.

Давайте начнем с разговора о том, что такое класс и объект .

Классы и объекты, концептуально

Итак, что является классом ? Многие люди определяют его как проект или шаблон для объекта. Фактически, вы можете прочитать больше О классах в PHP здесь . И в какой-то степени это то, что есть на самом деле. Давайте рассмотрим класс:

class Person {
    public $name = 'my name';
    public function sayHello() {
        echo "Hello";
    }
}

Как вы можете сказать, в этом классе есть свойство с именем $name и метод (функция) с именем sayHello().

Очень очень важно отметить, что класс является статической структурой. Это означает, что класс Person, когда-то определенный, всегда один и тот же везде, где бы вы на него ни смотрели.

С другой стороны, объект - это то, что называется экземпляром класса. Это означает, что мы берем «план» класса и используем его для создания динамической копии. Эта копия теперь специально привязана к переменной, в которой она хранится. Поэтому любые изменения в экземпляре являются локальными для этого экземпляра.

$bob = new Person;
$adam = new Person;
$bob->name = 'Bob';
echo $adam->name; // "my name"

Мы создаем новые экземпляры класса, используя оператор new.

Следовательно, мы говорим, что Класс является глобальной структурой, а Объект является локальной структурой. Не беспокойтесь об этом забавном синтаксисе ->, мы немного углубимся в это.

Еще одна вещь, о которой мы должны поговорить, это то, что мы можем проверить , является ли экземпляр instanceof конкретным классом: $bob instanceof Person, который возвращает логическое значение, если экземпляр $bob было сделано с использованием класса Person, или потомка Person.

Определение состояния

Итак, давайте немного углубимся в то, что на самом деле содержит класс. Существует 5 типов «вещей», которые содержит класс:

  1. Свойства - Думайте о них как о переменных, которые будет содержать каждый экземпляр.

    class Foo {
        public $bar = 1;
    }
    
  2. Статические свойства - Думайте о них как о переменных, которые являются общими на уровне класса. Это означает, что они никогда не копируются каждым экземпляром.

    class Foo {
        public static $bar = 1;
    }
    
  3. Методы - Это функции, которые каждый экземпляр будет содержать (и работать с экземплярами).

    class Foo {
        public function bar() {}
    }
    
  4. Статические методы - Это функции, которые являются общими для всего класса. Они не работают на экземплярах, а вместо этого только на статических свойствах.

    class Foo {
        public static function bar() {}
    }
    
  5. Константы - Константы с разрешением класса. Не вдаваясь в подробности, добавим для полноты:

    class Foo {
        const BAR = 1;
    }
    

Итак, в основном, мы храним информацию о классе и контейнере объектов, используя «подсказки» о static , которые определяют, является ли информация общей (и, следовательно, статической) или нет (и, следовательно, динамической).

Состояние и методы

Внутри метода экземпляр объекта представлен переменной $this. Текущее состояние этого объекта есть, и изменение (изменение) любого свойства приведет к изменению этого экземпляра (но не других).

Если метод вызывается статически, переменная $this не определена . Это потому, что нет никакого экземпляра, связанного со статическим вызовом.

Интересно, как выполняются статические вызовы. Итак, давайте поговорим о том, как мы получаем доступ к состоянию:

Доступ к состоянию

Итак, теперь, когда мы сохранили это состояние, нам нужно получить к нему доступ. Это может быть немного сложно (или больше больше, чем немного), поэтому давайте разделим это на две точки зрения: снаружи экземпляра / класса (скажем, из обычного вызова функции или из глобальной области видимости) и внутри экземпляра / класса ( изнутри метода объекта).

Снаружи экземпляра / класса

Снаружи экземпляра / класса наши правила довольно просты и предсказуемы. У нас есть два оператора, и каждый немедленно сообщает нам, если мы имеем дело с экземпляром или статическим классом:

  • -> - объект-оператор - это всегда используется, когда мы обращаемся к экземпляру.

    $bob = new Person;
    echo $bob->name;
    

    Важно отметить, что вызов Person->foo не имеет смысла (поскольку Person является классом, а не экземпляром). Следовательно, это ошибка разбора.

  • :: - оператор разрешения области действия - всегда используется для доступа к статическому свойству или методу класса.

    echo Foo::bar()
    

    Кроме того, мы можем вызвать статический метод для объекта таким же образом:

    echo $foo::bar()
    

    Это чрезвычайно важно отметить, что когда мы делаем это снаружи экземпляр объекта скрыт от метода bar(). Это означает, что это то же самое, что и выполнение:

    $class = get_class($foo);
    $class::bar();
    

Следовательно, $this не определено в статическом вызове.

Изнутри экземпляра / класса

Здесь все немного меняется. Используются те же операторы, но их значение становится значительно размытым.

Объект-оператор -> по-прежнему используется для выполнения вызовов состояния экземпляра объекта.

class Foo {
    public $a = 1;
    public function bar() {
        return $this->a;
    }
}

Вызов метода bar() для $foo (экземпляр Foo) с использованием объекта-оператора: $foo->bar() приведет к версии экземпляра $a.

Так мы и ожидаем.

Значение оператора :: меняется. Это зависит от контекста вызова текущей функции:

  • В статическом контексте

    В статическом контексте любые вызовы, сделанные с использованием ::, также будут статичный. Давайте рассмотрим пример:

    class Foo {
        public function bar() {
            return Foo::baz();
        }
        public function baz() {
            return isset($this);
        }
    }
    

    Вызов Foo::bar() вызовет метод baz() статически, и, следовательно, $this не будет заполняться . Стоит отметить, что в последних версиях PHP (5.3+) это вызовет ошибку E_STRICT, потому что мы вызываем нестатические методы статически.

  • В контексте экземпляра

    В контексте экземпляра, с другой стороны, вызовы, сделанные с использованием ::, зависят от получателя вызова (метода, который мы вызываем). Если метод определен как static, то он будет использовать статический вызов. Если это не так, он перешлет информацию об экземпляре.

    Итак, глядя на приведенный выше код, вызов $foo->bar() вернет true, поскольку «статический» вызов происходит внутри контекста экземпляра.

Имеет смысл? Я так не думал. Это сбивает с толку.

Сокращенные ключевые слова

Поскольку связывать все вместе, используя имена классов, довольно грязно, PHP предоставляет 3 основных «быстрых» ключевых слова, чтобы упростить разрешение области.

  • self - Это относится к имени текущего класса. Таким образом, self::baz() совпадает с Foo::baz() в классе Foo (любой метод на нем).

  • parent - Это относится к родителю текущего класса.

  • static - Это относится к вызываемому классу. Благодаря наследованию дочерние классы могут переопределять методы и статические свойства. Поэтому вызов их с использованием static вместо имени класса позволяет нам определить источник вызова, а не текущий уровень.

Примеры

Самый простой способ понять это - начать смотреть на некоторые примеры. Давайте выберем класс:

class Person {
    public static $number = 0;
    public $id = 0;
    public function __construct() {
        self::$number++;
        $this->id = self::$number;
    }
    public $name = "";
    public function getName() {
        return $this->name;
    }
    public function getId() {
        return $this->id;
    }
}

class Child extends Person {
    public $age = 0;
    public function __construct($age) {
        $this->age = $age;
        parent::__construct();
    }
    public function getName() {
        return 'child: ' . parent::getName();
    }
}

Теперь мы также рассмотрим наследование здесь. На мгновение проигнорируйте, что это плохая объектная модель, но давайте посмотрим, что произойдет, когда мы поиграем с этим:

$bob = new Person;
$bob->name = "Bob";
$adam = new Person;
$adam->name = "Adam";
$billy = new Child;
$billy->name = "Billy";
var_dump($bob->getId()); // 1
var_dump($adam->getId()); // 2
var_dump($billy->getId()); // 3

Таким образом, счетчик идентификаторов является общим для обоих экземпляров и дочерних элементов (потому что мы используя self для доступа к нему. Если бы мы использовали static, мы могли бы переопределить его в дочернем классе).

var_dump($bob->getName()); // Bob
var_dump($adam->getName()); // Adam
var_dump($billy->getName()); // child: Billy

Обратите внимание, что мы каждый раз выполняем метод Person::getName() instance . Но мы используем parent::getName(), чтобы сделать это в одном из случаев (дочерний случай). Вот что делает этот подход мощным.

Слово предостережения № 1

Обратите внимание, что вызывающий контекст - это то, что определяет, используется ли экземпляр. Следовательно:

class Foo {
    public function isFoo() {
        return $this instanceof Foo;
    }
}

Не всегда всегда верно.

class Bar {
    public function doSomething() {
        return Foo::isFoo();
    }
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)

Теперь действительно странно здесь. Мы вызываем другой класс, но $this, который передается методу Foo::isFoo(), является экземпляром $bar.

Это может вызвать всевозможные ошибки и концептуальные WTF-ошибки. Поэтому я настоятельно рекомендую избегать использования оператора :: из методов экземпляра для чего-либо, кроме этих трех виртуальных «сокращенных» ключевых слов (static, self и parent).

Слово предостережения № 2

Обратите внимание, что статические методы и свойства являются общими для всех. Это делает их в основном глобальными переменными. Со всеми теми же проблемами, которые идут с глобалами. Так что я бы не решался хранить информацию в статических методах / свойствах, если вы не уверены, что она действительно глобальная.

Слово предостережения № 3

В общем, вы захотите использовать то, что известно как Late-Static-Binding, используя static вместо self. Но обратите внимание, что это не одно и то же, поэтому выражение «всегда использовать static вместо self действительно недальновидно. Вместо этого остановитесь и подумайте о вызове, который вы хотите сделать, и подумайте, хотите ли вы, чтобы дочерние классы были возможность переопределить этот вызов static resolved .

TL / DR

Жаль, вернитесь и прочитайте его. Это может быть слишком долго, но это так долго, потому что это является сложной темой

TL / DR # 2

Хорошо, хорошо. Короче говоря, self используется для ссылки на текущее имя класса внутри класса, где $this ссылается на текущий экземпляр объекта . Обратите внимание, что self является сокращенным копированием / вставкой. Вы можете смело заменить его именем класса, и оно будет работать нормально. Но $this - это динамическая переменная, которая не может быть определена заранее (и может даже не быть вашим классом).

TL / DR # 3

Если используется объект-оператор ( ->), то вы всегда знаете, что имеете дело с экземпляром. Если scope-resolutio Используется n-оператор (::), вам нужна дополнительная информация о контексте (мы уже в объект-контексте? Мы вне объекта? и т.д.).

1
задан MetaGuru 23 June 2009 в 15:50
поделиться

1 ответ

Вы можете сделать это декларативно:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
        CellPadding="4" DataKeyNames="id" DataSourceID="sqlWorkFlowItems" 
        ForeColor="#333333" GridLines="None" 
        OnRowDeleting="GridView1_RowDeleting">

Или в коде (я думаю, вы только что пропустили + =):

GridView1.RowDeleting += new GridViewDeleteEventHandler(GridView1_RowDeleting);
2
ответ дан 3 September 2019 в 01:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: