Интерфейс это вариант, при условии что оба класса его реализуют. А разделение на методы — это вынос проблемы на уровень выше, вызывающему коду теперь нужно принимать решение о том, какой метод вызвать.
К сожалению, из-за особенностей типизации PHP, статистически анализаторы много-где не могут помочь. Например, отсутствие возможности перегрузки методов вынуждает отказываться даже от typehintig-га.
public void method (ClassA a) {
// ...
}
public void method (ClassB a) {
// ...
}
в PHP превращается в
public method ($a) {
// работаем без поддержки анализатора =(
}
Три причины:
1. Использование рефликсия является самым очевидным способом, обойти интерфейс и запихать в приватное поле все что вздумается, а в исходном комменте заявлено несколько способов.
2. Я точно знаю как «сломать» коллекцию через рефликсию, хочется увидеть что-то новое, чего я не знаю.
3. Я не очень хорошо знаком с возможностями рефлексии в других языках, но у верен, что в C# можно с ее помощью сломать даже местные дженерики.
Собственно, выше я писал вариант для этого. Но суть «спора» в том, что я рассуждаю с позиции того, что сейчас есть в языке (собственно, я так и написал в моей первом комменте).
Пока в ПХП такая типизация, какая она есть, без костылей с аннотациями, к сожалению не обойтись, но кажется я вас понял. Если бы дженерики были нативные, то приведенный ниже код гарантировал бы, что внутри функции useCollection все элементы $posts являются экземплярами класса Post (если это не так, то будет эксешпшен при вызове).
function useCollection(Collection<Post> $posts) {
// ....
}
Мой код позволяет добиться такого поведения, без особых заморочек:
function useCollection(Collection $posts) {
if (!$posts->isInstanceOf(Post::class)) {
throw new InvalidArgumentException();
}
/** @var Post[] $posts */
// ....
}
Это 100% гарантирует, что каждый элемент коллекции является экземпляром Post
Дело вот в чем:
abstract public mixed offsetGet ( mixed $offset )
Никакие решения на базе mixed не позволят избавить клиентский код от необходимости проверок типа элементов коллекции.
Если вы внимательно посмотрите в мою реализацию метода offsetGet, то увидите, что в коллекцию могут быть добавлены только объекты того класса, который был указан при создании коллекции, так что необходимости проверять каждый элемент коллекции перед использованием нет.
А что проверяем-то? То что хром умеет к переменной 50 прибавлять?
Наверно вот такой код имелся ввиду:
function kissMiss(){
let startTime = new Date();
for(let i = 1, t=50; i<=100; i++, t+=50) {
setTimeout(()=>{
let s = '';
s = !(i%3) ? 'Miss': '';
s += !(i%5) ? 'Kiss': '';
s = s ? s : i;
console.log((new Date() - startTime) + ' >> ' + t +' >> '+s);
},t);
}
}
Но по большому счеты, эксперимент показывает что setTimeout вполне подходит, у меня в хроме ровно 50мс между вызовами, хотя до первого чуть-больше.
в PHP превращается в
1. Использование рефликсия является самым очевидным способом, обойти интерфейс и запихать в приватное поле все что вздумается, а в исходном комменте заявлено несколько способов.
2. Я точно знаю как «сломать» коллекцию через рефликсию, хочется увидеть что-то новое, чего я не знаю.
3. Я не очень хорошо знаком с возможностями рефлексии в других языках, но у верен, что в C# можно с ее помощью сломать даже местные дженерики.
Прошу, приведите пример кода, но без использования рефлексии.
Т.е. делает тоже самое, что и указание джинерика в сигнатуре метода.
Мой код позволяет добиться такого поведения, без особых заморочек:
Это 100% гарантирует, что каждый элемент коллекции является экземпляром Post
Если вы внимательно посмотрите в мою реализацию метода offsetGet, то увидите, что в коллекцию могут быть добавлены только объекты того класса, который был указан при создании коллекции, так что необходимости проверять каждый элемент коллекции перед использованием нет.
Похоже мы с вами друг-друга не понимаем. Будьте добры, приведите пример, как вы будите использовать джинерики, для отличия
от
Обе строчки «равнозначны».
Единственное чего не хватает, так это дополнения в IDE. Но и как выше говорили, достаточно нормально следить за заполнением массива.UPD: Если указать тип для $postCollection через PHPDoc как массив постов, то будет подсказывать
Наверно вот такой код имелся ввиду:
Но по большому счеты, эксперимент показывает что setTimeout вполне подходит, у меня в хроме ровно 50мс между вызовами, хотя до первого чуть-больше.