¿Cómo aclarar que un método puede ser anulado?

7

Tengo una biblioteca que uso en varias aplicaciones. Tiene un método que devuelve una URL:

class UrlBuilder {
  public function url($config) {
    $config = do_some_checks($config);
    return make_url($config));
  }
}

A menudo, una aplicación quiere alterar la forma en que se crea la URL, y me gustaría dejarlo claro a partir de la forma en que se implementa la biblioteca. Se me ocurrieron estas soluciones:

  1. Mencione esto en los documentos de la biblioteca, pero de lo contrario, simplemente deje que la aplicación anule el método como cualquier otro:

    class MyAppUrlBuilder extends UrlBuilder {
      public function url($config) {
        $config = do_some_checks($config);
        return make_url_differently($config);
      }
    }
    
  2. Llama a una función separada que está justo ahí para ser anulada:

    class UrlBuilder {
      public function url($config) {
        $config = do_some_checks($config);
        $config = $this->alterConfig($config);
        return make_url($config));
      }
    
      protected function alterConfig($config) { return $config; }
    }
    
  3. Proporcione un configurador para establecer una devolución de llamada de personalización:

    class UrlBuilder {
      public function url($config) {
        $config = do_some_checks($config);
        if ($this->configModifier)
          $config = $this->configModifier($config);
        return make_url($config));
      }
    
      public function setConfigModifier($configModifier) {
        $this->configModifier = $configModifier;
      }
    }
    

¿Hay alguna diferencia semántica y (si eso no es una cuestión de gusto) es preferible alguno de ellos?

    
pregunta AndreKR 28.04.2016 - 05:32

1 respuesta

9

Prefiero la opción # 4: Evitar confiar en la herencia.

Simplemente haga de UrlBuilder una interfaz , y ofrezca a las personas alguna forma de inyectar su propia implementación al proceso, anulando el valor predeterminado que proporcionó.

interface UrlBuilder {
    public function url($config);
}

class DefaultUrlBuilder implements UrlBuilder{
  public function url($config) {
    $config = do_some_checks($config);
    return make_url($config));
  }
}

De esta manera, se desplaza la responsabilidad: no es necesario que se preocupe demasiado por todas las formas posibles en que podrían querer subclasificar su implementación, ya que no tienen a. Si sus necesidades son simples y las subclasifican, bueno, bueno para ellas, encontraron un atajo. Si sus necesidades son complejas, bueno, tienen la libertad de hacer otra cosa.

... Dicho esto, de las tres opciones, mi favorito es el # 2, si tienes una visión muy clara de lo que querrán personalizar.

    
respondido por el Darien 28.04.2016 - 07:19

Lea otras preguntas en las etiquetas