PHP5. Необходимость явного указывания конструктора

Посмотрите на следующий класс

class Tester {
      
        // tester name
        private $name;
        

        // set tester name
        public function tester($name = 'undefined') {
            $this->name = $name;
        }
 

 }

Да, структура его очень проста, обратите внимание на метод tester, допустим, что мы хотим так запроектировать этот класс, чтобы tester был именно методом, который будет устанавливать текущее имя тестера. Если попробовать инстанцироваться от этого класса, то это приведет к вызову данного метода, так как в данном контексте он будет восприниматься как конструктор, и это несмотря на то, что метод прописан строчно в отличии от имени класса, это отголоски более старых версий PHP. Чтобы все же решить нашу задачу, необходимо в обязательном порядке указывать конструктор


class Tester {
      
        // tester name
        private $name;
      
        public function __construct() {}
      
        // set tester name
        public function tester($name = 'undefined') {
            $this->name = $name;
        }
 

}

или лучше так

class Tester {
      
        // tester name
        private $name;
      
        public function __construct($name = 'undefined') {
            $this->tester($name);
        }
      
        // set tester name
        public function tester($name = 'undefined') {
            $this->name = $name;
        }
 

}

Вот пример реализации данного класса

class Tester {
       
        // tester name
        private $name;
        // break
        private $br;
       
        public function __construct($name = 'undefined') {
            $this->tester($name);
            $this->br = "<br/>";
        }
       
        // set tester name
        public function tester($name = 'undefined') {
            $this->name = $name;
        }
       
        // get tester name
        public function getName() {
            echo "{$this->name}{$this->br}";
        }

 } 


$tester = new Tester();
$tester->getName(); // undefined
$tester->tester('Ivan');
$tester->getName(); // Ivan
$tester->tester('Petya');
$tester->getName(); // Petya
$tester->tester('Misha');
$tester->getName(); // Misha

Javascript. Авто инициализация объектов

Предположим, что нам необходимо после загрузки документа проинициализировать создаваемый объект. А вообще, зачем это может потребоваться? Если попытаться выполнить следующий участок кода, то мы обнаружим, что мы не можем напрямую обратиться к объекту App.

var App = (function() {
    (function(){
        console.log(App); // undefined
    })();
    return {
        version: 0
    };
})();


 Все правильно: пока объект не реализован, мы не можем обратиться к нему. Конечно, можно поступить проще, например, расположить метод инициализации ниже:

var App = (function() {
    return {
        version: 0
    }
})();

(function(){
    console.log(App); // App object
})();


Но в этом случае нарушается логическая связка с реализацией объекта, поэтому этот вариант мы отбрасываем. Далее рассмотрим возможные реализации инициализации на примере стека. Вот один из способов, правда он основан на использовании библиотеки jquery.

var Stack = (function(){

    var init = function() {
        try {
            for (var i = 0; i < 10; i++) {
                Stack.push(i);
            }
        } catch(e) {
            console.log(e.message);
        }
    };

    $(document).ready(function(){
        init();
    });
   
    return {
        size: 1024,
        pointer: 0,
        storage: [],
        push: function(item) {
            if (this.pointer + 1 > this.size) {
                throw new Error("Stack is full");
            }
            else {
                this.storage.push(item);
                this.pointer++;
            }
        },
        pop: function() {
            if (this.pointer == 0) {
                throw new Error("Stack is empty");
            }
            else {
                return this.storage[--this.pointer];
            }
        },
        reset: function() {
            this.storage = [];
            this.pointer = 0;
        }
    };
   
})()


Идея, заключается в том, что сама инициализация начинается только после полной загрузки документа, плюсом данной идеи также является и то, что у нас появляется уверенность в готовности и всех остальных объектов, которые так или иначе могут нам понадобиться. В случае, если мы не собираемся использовать jquery, тогда можно поступить следующим образом

var Stack = (function(){

    var init = function() {
        try {
            for (var i = 0; i < 1025; i++) {
                Stack.push(i);
            }
        } catch(e) {
            console.log(e.message); // Stack is full
        }
    };

    if (document.addEventListener) {
        document.addEventListener("DOMContentLoaded", init, false);
    }
    else if (document.attachEvent) {
        document.attachEvent("onreadystatechange", init);
    }
   
    return {
        size: 1024,
        pointer: 0,
        storage: [],
        push: function(item) {
            if (this.pointer + 1 > this.size) {
                throw new Error("Stack is full");
            }
            else {
                this.storage.push(item);
                this.pointer++;
            }
        },
        pop: function() {
            if (this.pointer == 0) {
                throw new Error("Stack is empty");
            }
            else {
                return this.storage[--this.pointer];
            }
        },
        reset: function() {
            this.storage = [];
            this.pointer = 0;
        }
    };
   
})()


Здесь мы воспользовались обработчиками событий загрузки документа для различных браузеров (document.addEventListener, document.attachEvent), эти же обработчики использованы в реализации самого метода ready в jquery. Есть еще один способ авто инициализации

var Stack = (function(){

    var init = function() {
        try {
            for (var i = 0; i < 10; i++) {
                Stack.push(i);
            }
        } catch(e) {
            console.log(e.message);
        }
    };

    setTimeout(function() {
        init();
    }, 0);
   
    return {
        size: 1024,
        pointer: 0,
        storage: [],
        push: function(item) {
            if (this.pointer + 1 > this.size) {
                throw new Error("Stack is full");
            }
            else {
                this.storage.push(item);
                this.pointer++;
            }
        },
        pop: function() {
            if (this.pointer == 0) {
                throw new Error("Stack is empty");
            }
            else {
                return this.storage[--this.pointer];
            }
        },
        reset: function() {
            this.storage = [];
            this.pointer = 0;
        }
    };
   
})()


или вот так

var Stack = {
    size: 1024,
    pointer: 0,
    storage: [],
    push: function(item) {
        if (this.pointer + 1 > this.size) {
            throw new Error("Stack is full");
        }
        else {
            this.storage.push(item);
            this.pointer++;
        }
    },
    pop: function() {
        if (this.pointer == 0) {
            throw new Error("Stack is empty");
        }
        else {
            return this.storage[--this.pointer];
        }
    },
    reset: function() {
        this.storage = [];
        this.pointer = 0;
    },
    init: (function() {
        var init = function() {
            try {
                for (var i = 0; i < 10; i++) {
                    Stack.push(i);
                }
            } catch(e) {
                console.log(e.message);
            }
            return 0;
        };
        setTimeout(function() {
            init();
        }, 0);
    })()
};


Использование таймера в авто инициализации также дает возможность обращаться к объекту. Для сравнения приведенных выше методов, приведу следующий качественный тест:

var start = new Date().getTime();
$(document).ready(function(){
    console.log('ready: ' + (new Date().getTime() - start) + ' ms');
});
setTimeout(function() {
    console.log('timer: ' + (new Date().getTime() - start) + ' ms');
}, 0);
console.log('first: ' + (new Date().getTime() - start) + ' ms');
console.log('last: ' + (new Date().getTime() - start) + ' ms');


Результат этого теста выглядит следующим образом:

// FF
first: 1 ms
last:  2 ms
timer: 9 ms
ready: 12 ms

// Chrome
first: 0 ms
last:  0 ms
ready: 4 ms
timer: 23 ms

// Opera
first: 0 ms
last:  0 ms
ready: 0 ms
timer: 23 ms

// IE
first: 0 ms
last:  0 ms
ready: 19 ms
timer: 26 ms


В целом по скорости быстрее начинает выполнение метод ready, в то время как setTimeout запускается позже, это справедливо для IE, Opera, Chrome, а FF показал другие результаты, видимо это зависит от их движка. У вас могут получиться другие значения, но в целом картина схожа.