1
votes

Comment éviter d'implémenter une méthode avec des paramètres inutiles pour satisfaire les conditions d'interface?

J'ai une interface IFoo avec une méthode Bar, prenant un argument string. Cette interface a une implémentation qui renvoie une valeur constante, sans utiliser l'argument du tout. L'autre utilise les paramètres.

Comment éviter ce paramètre inutile? Voici une implémentation factice

  public interface IFoo
    {
        string Bar(string parameter);
    }

    public class Foo : IFoo
    {
        public string Bar(string parameter)
        {
            return string.Format("{0}Fooooooo", parameter);
        }
    }

    public class ConstantFoo : IFoo
    {
        public string Bar(string parameter)
        {
            return "Baaaaaaar";
        }
    }

    public class Caller
    {
        private readonly IFoo _foo;
        private readonly IFoo _constFoo;
        public Caller()
        {
            _foo = new Foo();
            _constFoo = new ConstantFoo();
        }
        public void DummyUsage()
        {
            string arg = "Wololo";
            Console.WriteLine(_foo.Bar(arg));
            Console.WriteLine(_constFoo.Bar(arg));

        }
    }


5 commentaires

Interface définissant le contrat. Vous n'êtes pas obligé d'utiliser ce paramètre. Un autre cas est par exemple les événements .. Imaginez que Microsoft vous fournisse des événements. Habituellement, la méthode du gestionnaire d'événements a 2 arguments void MyHandler (expéditeur de l'objet, EventArgs e) Une fois l'événement déclenché, ce hndler est appelé et 2 arguments sont utilisables dans la portée de la méthode. Vous pouvez les utiliser mais il n'y a pas de force pour vous forcer à les utiliser. La même chose que vous pouvez appliquer à l'interface (tierce partie) dans le cas où vous êtes producteur d'interface, peut-être que vous pouvez réfléchir à la façon de changer la conception de votre application.


L'interface est un contrat. Lorsque vous avez une instance de IFoo , vous savez seulement qu'il a Bar (string) et vous ne savez pas si le paramètre est inutile ou non, vous devez le passer. Ce n'est pas grave si l'implémentation ne l'utilise pas, mais elle doit quand même suivre un contrat et définir ce paramètre comme signature de méthode. Vous pouvez lui donner un nom sophistiqué, par exemple notUsed et même donner une valeur par défaut facultative (ou utiliser une surcharge), alors si vous avez une instance de ConstantFoo , vous pouvez appeler Bar () sans paramètre


Exemple de commentaire de Sinatr: dotnetfiddle.net/I9rrkD


@Fildor je pense que dans ce cas, les arguments optionnels ne sont pas une bonne idée


@PeterM. Je viens de compiler un exemple de ce que Sinatr a proposé à OP de voir.


3 Réponses :


1
votes

La signature d'une fonction ou d'une propriété qu'une classe implémente doit toujours être identique à l'interface respective. Si vous avez vous-même le contrôle de l'interface, vous pouvez modifier la signature à la fois dans l'interface et dans la classe d'implémentation.

public interface IFoo
{
    string Bar();
}

public class Foo : IFoo
{
    public string Bar()
    {
        return "Fooooooo";
    }
}

Si ce n'est pas ce que vous voulez, cela peut suggérer que votre modèle d'héritage est pas très bien défini.


1 commentaires

où vous avez perdu le paramètre .. comment est défini?



0
votes

Déclarez une méthode supplémentaire Bar () sans aucun paramètre dans l'interface IFoo

public interface IFoo
{
    string Bar(string parameter);

    string Bar();
}

public class Foo : IFoo
{
    public string Bar(string parameter)
    {
        return string.Format("{0}Fooooooo", parameter);
    }

    public string Bar()
    {
        return string.Empty;
    }
}

public class ConstantFoo : IFoo
{
    public string Bar(string parameter)
    {
        return string.Empty;
    }

    public string Bar()
    {
        return "Baaaaaaar";
    }
}

public class Caller
{
    private readonly IFoo _foo;
    private readonly IFoo _constFoo;
    public Caller()
    {
        _foo = new Foo();
        _constFoo = new ConstantFoo();
    }
    public void DummyUsage()
    {
        string arg = "Wololo";
        Console.WriteLine(_foo.Bar(arg));
        Console.WriteLine(_constFoo.Bar());

    }
}


0 commentaires

0
votes

Votre exemple compte avec un fait. En tant que producteur de classe, vous connaissez les détails de l'implémentation que vous savez exactement quel type d'instance est IFoo

public class Caller
    {
        private readonly IParametrizedFoo _parametrizedFoo;
        private readonly IFoo _foo;
        public Caller(IParametrizedFoo parametrizedFoo, IFoo foo)
        {
            _parametrizedFoo= parametrizedFoo;
            _foo= foo;
        }
        public void DummyUsage()
        {
            string arg = "Wololo";
            Console.WriteLine(parametrizedFoo.Bar(arg));
            Console.WriteLine(_foo.Bar());

        }

Maintenant, pensez à propos de ceci:

public class Foo : IParametrizedFoo
    {
        public string Bar(string parameter)
        {
            return string.Format("{0}Fooooooo", parameter);
        }
    }

    public class ConstantFoo : IFoo, IParametrizedFoo
    {
        public string Bar()
        {
            return "Baaaaaaar";
        }

      string  IParametrizedFoo.Bar(string parameter)
{
Bar();
}
    }

Maintenant un autre

Imaginez que vous avez 2 interfaces:

interface IFoo 
{
    void Bar();
}

interface IParametrizedFoo
{
    void Bar(string parameter);
}

alors vous pouvez avoir la mise en œuvre

public class Caller
    {
        private readonly IEnumerable<IFoo> _fooServices;

        public Caller(IEnumerable<IFoo> fooServices)
        {
            _fooServices = fooServices;
        }
        public void DummyUsage()
        {
            string arg = "Wololo";

           foreach(IFoo fooService in _fooServices)
          {
               Console.WriteLine(fooService.Bar(arg)); //==> you do not know what type of foo it is if it require internally argument or not .. But you have to pass it to satisfy contract defined by IFoo interface
          }

        }

puis l'utilisation

public class Caller
    {
        private readonly IFoo _foo;
        private readonly IFoo _constFoo;
        public Caller()
        {
            _foo = new Foo();   // => here is exact instance type
            _constFoo = new ConstantFoo(); // => here is exact instance type
        }
        public void DummyUsage()
        {
            string arg = "Wololo";
            Console.WriteLine(_foo.Bar(arg)); // -> here you know that you need parameterarg
            Console.WriteLine(_constFoo.Bar(arg)); // -> here you know that you do not need parameter arg

        }

Mais je ne pense toujours pas que ce soit le meilleur conception


0 commentaires