Абстрактные классы и интерфейсы

grigori

( ͡° ͜ʖ ͡°)
Команда форума
это же мой любимый вопрос на собеседовании! :)
заучить эту тему невозможно - или прочувствовал на себе, или нет
 

EvgeTrofi

Новичок
Здравствуйте! Помогите пожалуйста разобраться. Возможно ли поменять значение статической переменной, находящейся в абстрактном классе из дочернего класса?
Как это сделать?
Вот пример кода:
PHP:
	abstract class AbstC{
		protected static $dir;
		public static function start(){
			echo self::$dir."<br />";
		}
	}
	class RunClass extends AbstC {
		protected static $dir="меняем переменную";
	}
	$test_txt = RunClass::start();
	echo "$test_txt";
 

radioheaded

PHP нуб
Здравствуйте! Помогите пожалуйста разобраться. Возможно ли поменять значение статической переменной, находящейся в абстрактном классе из дочернего класса?
Как это сделать?
Вот пример кода:
PHP:
	abstract class AbstC{
		protected $dir;
		public static function start(){
			echo self::$dir."<br />";
		}
	}
	class RunClass extends AbstC {
		protected $dir="меняем переменную";
	}
	$test_txt = RunClass::start();
	echo "$test_txt";
У вас в абстрактном классе нет статических переменных.
 
  • Like
Реакции: AmdY

WMix

герр M:)ller
Партнер клуба
возможно
но, твоя переменная не статичная, self в методе start указывает на AbstC
 

hell0w0rd

Продвинутый новичок
PHP:
abstract class Extension
{
    public function __construct(array $config = array())
    {
        $this->config($config);
        $this->init();
    }
    abstract protected function init();
    abstract protected function config(array $config = array());
}

class MyExt extends Extension
{
    protected function init()
    {
        echo 'Инициализация';
    }
    protected function config(array $config = array())
    {
        echo 'Настройка';
    }
}

$ext = new MyExt();
Попробуй исполнить такой код и сразу поймешь смысл абстрактных классов. Когда не нужны связи - просто пишете интерфейс.
 

EvgeTrofi

Новичок
Спасибо GusakovNick!
А без создания объекта возможно изменить значение переменной (свойства) в родительском абстрактном классе через дочерний?
Я не хочу использовать new. Хочу сразу получить результат в переменную через ::
PHP:
	abstract class AbstC{
		protected $dir;
		public static function start(){
			return(self::$dir);
		}
	}
	class RunClass1 extends AbstC {
		protected $dir="меняем значение переменной в первом классе";
	}
	class RunClass2 extends AbstC {
		protected $dir="меняем значение переменной во втором классе";
	}
	$test_txt1 = RunClass1::start();
	$test_txt2 = RunClass2::start();
	
	echo "$test_txt1<br />$test_txt2";
 

hell0w0rd

Продвинутый новичок
EvgeTrofi
Со статическими полями все сложнее обстоит. Не может быть статическая функция абстрактной, например.
Еще такая веселость - если написать функцию такого рода:
PHP:
protected function getDir()
{
  return __DIR__;
}
В абстрактном классе, а затем не переопределить в наследуемом, она всегда будет возвращать директорию абстракного класса.
Вообще асбтрактные классы нужны для расширяемости и единого API классов. Все возможные расширения, плагины, разные системы с единым API - кешеры, драйверы баз данных.
https://github.com/doctrine/cache/tree/master/lib/Doctrine/Common/Cache - вот популярный кешер
Там есть оба интересуемых вас типа, посмотрите, поймете все до конца)
 

Adelf

Administrator
Команда форума
craz
помоему там слишком просто и один не самый понятный пример. У меня редко бывают сомнения что делать классом, а что интерфейсом. Абстрактный класс говорит о том, что его наследники будут представлять собой какую-то четко определенную сущность. Интерфейсы же обычно говорят о возможности обьекта что-то делать, не более того.
 

Adelf

Administrator
Команда форума
craz
ну вот если бы него было не Door и Alarm, а Alarm and KnockKnock он что бы сделал? не обьяснил же сути.
 

craz

Нестандартное звание
class KnockKnockDoor extends Door implements KnockKnock {

я вот так понял это...
 

Adelf

Administrator
Команда форума
craz
угу. это показывает, что проблемы "абстракный класс или интерфейс" - попросту нет. все очевидно.

И да. Без привязки к сущности - легко. У нас был бы обьект, которому просто надо стучать где ни попадя. и ему нужен был бы только interface KnockKnockable чтобы проверять обьекты на его наличие и стучать :)
 

WMix

герр M:)ller
Партнер клуба
EvgeTrofi
А без создания объекта возможно изменить значение переменной (свойства) в родительском абстрактном классе через дочерний?
self в методе start указывает на AbstC
PHP:
    abstract class AbstC{
       static protected $dir;
        public static function start(){
            return(self::$dir);
        }
    }
    class RunClass2 extends AbstC {
       static protected $dir="меняем значение переменной во втором классе";

        // придется переписать метод
        public static function start(){
            return(self::$dir); 
        }
    }
echo RunClass2::start();
 

EvgeTrofi

Новичок
Нет. всётаки если повторить метод в дочернем классе, то в родительском он не будет выполняться.
Вот например сложение должно выполняться в абстрактном родительском классе, а значения для вычислений должны формироваться в дочернем статичном. Как быть в такой ситуации?
PHP:
	abstract class AbstC{
		protected static $a;
		protected static $b;
		public static function summ(){
			echo "Выполнение абстрактного класса...<br />";
			$result = self::$a+self::$b;
			return($result);
		}
	}
	class RunClass extends AbstC {
		protected static $a=2;
		protected static $b=3;		
		public static function summ(){
			echo "Выполнение дочернего класса...<br />";
			self::$a=2;
			self::$b=3;
		}
	}
	$test_txt1 = RunClass::summ();
	
	echo "$test_txt1<br />";
 

Adelf

Administrator
Команда форума
PHP:
<?php

  abstract class AbstC{
        protected static $a;
        protected static $b;
        public static function summ(){
            echo "BaseClass...<br />";
            $result = self::$a+self::$b;
            return $result;
        }
    }
    class RunClass extends AbstC {
        public static function summ(){
            echo "RunClass...<br />";
            self::$a=2;
            self::$b=3;

            return parent::summ();
        }
    }
    $test_txt1 = RunClass::summ();
    
    echo "$test_txt1<br />";
 
Сверху