Разные интерфейсы, одинаковые методы

Lionishy

Новичок
WMix, нет, не тоже самое.
Для полноты ощущений можно объявить методы resolveCat и resolveDog защищёнными.
В примере с RadioFacade меняется сигнатура методов для громкости и частоты. В С++ примере открытый интерфейс имеет два метода с одинаковой сигнатурой.

hellow0rd
Озвучивание реальных названий интерфейсов не поможет Вам сделать какое-либо более красивое решение, чем с котопсом.
Раскрытие существенной части архитектуры моей части проекта скорее приведёт к попыткам создать какие-либо швы в других частях архитектуры.

я не настолько глупа, чтобы в обществе таких благородных людей держать при себе ключи
 
Последнее редактирование:

WMix

герр M:)ller
Партнер клуба
напиши конечный вызов того что ты хочешь!
PHP:
<?php
interface IResolver{
    public function resolve();
};

interface IResolveDog extends IResolver{};
interface IResolveCat extends IResolver{};


class Cat implements IResolveCat{
    public function resolve(){
        echo "I'm a CAT";
    }
}

class Dog implements IResolveDog{
    public function resolve(){
        echo "I'm a DOG";
    }
}

class Resolver{
    public function resolve( IResolver $r ){
        $r->resolve();
    }
};


$resolver = new Resolver;
$resolver->resolve( new Cat );
$resolver->resolve( new Dog );
 

hell0w0rd

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

Lionishy

Новичок
WMix,
PHP:
interface IOpenable {
    public function action();
};

interface ICloseable {
    public function action();
};

class Door implements IOpenable, IClosable {
    /* code goes here */
};

function knowHowToOpen(IOpenable $door)
{
  /* code goes here */
}

function knowHowToClose(ICloseable $door)
{
  /* code goes here */
}

/* instantate a door */
$door;

/* open a door */
KnowHowToOpen($door);

/* close a door */
KnowHowToClose($door);
 

accido

Новичок
fixxxer,
Один в один агрегатор интерфейсов. Мне уже предложенных на другом форуме. После пары итераций получилось:

PHP:
Interface IResolveDog {
    /**
    * @param Name
    * @return Dog
    */
    public function resolve(Name $name);
};

Interface IResolveCat {
    /**
    * @param Name
    * @return Cat
    */
    public function resolve(Name $name);
};

class CatDog {
    /* a lot of code goes here */

    /**
    * @return IResolveDog
    */
    public function asIResoveDog()
    {
        return new DogResolver($this);
    }

    /**
    * @return IResolveCat
    */
    public function asIResoveCat()
    {
        return new CatResolver($this);
    }
};

class DogResolver implements IResolveDog {
   public function __construct(CatDog $implementation)
   {
       /* construct Proxy */
   }

   /**
    * {@inheritdoc}
    */
    public function resolve(Name $name)
    {
        /* code for a dog goes here */
    }
};
Думаю, что такими декораторами можно решить более половины всех подобных случаев.



Если бы это был C++, то можно было расширить каждый из интерфейсов дополнительно и добавить по методу с другим названием, а потом оба унаследовать невиртуально и реализовать. Тогда в классе оказалось бы два разных метода с совершенно одинаковыми сигнатурами, но делающими совершенно разные вещи, потому что это были бы два совершенно разных метода.
В VC это можно сделать в точности, как в C#.


С C# ещё удобнее: просто два разных метода объявляются в классе и назначаются каждый на свой интерфейс.

Ясно, что разруливание такой ситуации, которая встречается чуть чаще, чем никогда не может быть простым. Но уровень удобства в цепочке PHP->Java->C++->C# понижается.
Вначале ты писал о том, что тебе в одном классе надо применить оба интерфейса, тут же ты привел типичную абстрактную фабрику, только вместо factory() имеем resolve(), но каждый экземпляр фабрики наследует только один из данных интерфейсов. Ты бы лучше определился с тем чего ты хочешь. Если хочешь, чтобы тебе что-то конкретное посоветовали просто покажи свое задание в более широком контексте, а то получается, что все это писано вилами по воде.
 

accido

Новичок
Признавайся какое у тебя задание? :) Кстати, где мой паяльник ...
 

Вурдалак

Продвинутый новичок
hell0w0rd, я в первую очередь про @return, etc. Когда у тебя интерфейс, тебе PhpStorm по очевидным причинам без @return не поможет.
 

riff

Новичок
Lionishy, Просто уточняющий вопрос: а переделать таким образом уже возможности нет? Ну чтобы было за что зацепиться при вызове действия.
PHP:
interface IЛюбойИнтерфейс {
    //общее действие с разной реализацией (openDoor = 1, closeDoor = 0)
    public function action(int $flag);
};
 

Lionishy

Новичок
accido, это похоже много на что. И на фабрику, и на фасад, и на адаптер.
В PHP нельзя реализовать два метода с одинаковой сигнатурой в классе, несмотря на то, что они могут принадлежать разным методам. Потому проектное решение: класс реализует два интерфейса -- не получится бес швов перенести на PHP. Вся эта конструкция с дополнительными сущностями и дополнительным интерфейсом -- шов между проектом и PHP. В подавляющем большинстве случаев это просто шов между проектированием и конструированием. То есть в реальном коде просто придётся каждый раз писать лишний вызов, но в остальном проект остаётся тем же самым.
 

Lionishy

Новичок
riff, вообще уже всё давно переделано.

PHP:
interface IResolveCat {
  public function resolveCat();
};

interface IResolveDog {
  public function resolveDog();
};
Было принято, что методы по-возможности следует именовать хотя бы в два слова.
Всё уже согласовано.
Однако могло быть и так, что эти интерфейсы пришли бы от тех людей, на которых я не могу повлиять.
И теперь я вооружён знанием, как в такой ситуации поступать.

Просто C++ я использую постоянно и даже преподаю. А вот PHP -- это "в дружбу". И я его плохо знаю. Плохо знаю возможности. А проектирую, конечно, от C++.

Так совпало, что в интерфейсе иерархической структуры был пустой метод resolve, который поступил от других разработчиков -- от по имени узла выдавал цепочку предков. Ну вот ударило в голову. И у меня был метод resolve, который по имени узла возвращал содержимое узла. Ну вот совпало так.

Слово гадкое. Им вообще всё, что угодно можно обозвать, как explain. Так просто нельзя методы называть. Это как action. Но такое могло произойти и в более логичной ситуации.
 

WMix

герр M:)ller
Партнер клуба
WMix,
PHP:
interface IOpenable {
    public function action();
};

interface ICloseable {
    public function action();
};

class Door implements IOpenable, IClosable {
    /* code goes here */
};

function knowHowToOpen(IOpenable $door)
{
  /* code goes here */
}

function knowHowToClose(ICloseable $door)
{
  /* code goes here */
}

/* instantate a door */
$door;

/* open a door */
KnowHowToOpen($door);

/* close a door */
KnowHowToClose($door);
это вообще не проблема
PHP:
function knowHowToOpen(IOpenable $door)
{
  $door->action()
}
 

WMix

герр M:)ller
Партнер клуба
В PHP нельзя реализовать два метода с одинаковой сигнатурой в классе, несмотря на то, что они могут принадлежать разным методам.
это врятли вообще можно реализовать и на плюсах тоже
 

hell0w0rd

Продвинутый новичок
WMix, нельзя конечно)) заговорилась просто дамочка, внезапно стало понятно, что преподавать и дело делать - разные вещи, и теория с практикой не совпадают. Теоретически знает тучу определений, а сказать на деле что именно нужно - не может.
 

hell0w0rd

Продвинутый новичок
Lionishy, прошу прощения за наезд выше.
На мой взгляд проблема вся в том, что не должно быть IResolveCat, должен быть IResolveAnimal, который знает не про Cat, или Dog, а про Animal.
Но как я понял проблема в том, что эти два интерфейса от двух разных проектов, тогда есть вариант решения без копипасты кода, но с созданием двух классов, потому что ни один язык не поддерживает наличие нескольких методов с одинаковой сигнатурой.
Создаете trait, который реализует дублирующую функциональность и далее инжектите в любой класс.
 

Lionishy

Новичок
hell0w0rd,
ни один язык не поддерживает наличие нескольких методов с одинаковой сигнатурой
Если строго, то да. Но методы IResolveCat::resolve и IResolveDog::resolve в действительности имеют различную сигнатуру, так как символ resolve ничего не значит, он находится в том или ином пространстве имён.

вот так это выглядит в C#

Код:
public interface IResolveDog {
    Dog resolve(Name);
}

public interface IResolveCat {
    Cat resolve(Name);
}

public class CatDog: IResolveCat, IResolveDog {

    Cat IResolveCat.resove(Name)
    {
        /* code for a Cat goes here */
    }

    Dog IResolveDog.resove(Name)
    {
        /* code for a Dog goes here */
    }
}
Как это выглядит в C++ -- я показал. В MSVC это можно сделать проще, используя __interface макрос. Компилятор всё поймёт и сгенерирует на стадии препроцессора код, идентичный стандартному решению.

В Java и PHP этого сделать нельзя в принципе, да.
 

hell0w0rd

Продвинутый новичок
Lionishy, я думаю что в php этого нельзя сделать, потому что на сигнатуру метода в данный момент никак не влияет тип возвращаемого значения, в отличии от C++ и C#.
Ну и такой подход в принципе сомнителен и по идее должен решаться раньше (На стадии Animal)
 

WMix

герр M:)ller
Партнер клуба
Lionishy, а можешь написать, плиз, полностью рабочий c++ код с main методом, чтоб только команду на компиляцию нужно было отдать? (желательно с учетом того о чем ты говорил, не 2 метода а один и тотже (сигнатура) 2 раза)
 
Сверху