Pregunta

Acabo de encontrar esta cita en un libro sobre OOP que estoy leyendo,

  

A un niño solo se le permite aumentar   funcionalidad y agregar funcionalidad.   A un niño nunca se le permite quitar   funcionalidad Si encuentras que un   el niño necesita eliminar la funcionalidad,   esto es una indicación de que el niño   debe aparecer antes que el padre en el   jerarquía de herencia!

Pero mi pregunta es, ¿no es esto lo que hace la anulación?

¿Fue útil?

Solución

Puede eliminar la funcionalidad anulando. Pero normalmente lo usas para cambiar el comportamiento. Para dejar que la clase se comporte como debería ser.

Si se elimina el comportamiento, a menudo es un signo de un mal diseño de clase.

Otros consejos

El niño no puede eliminar la funcionalidad; puede alterarla, pero no puede, por ejemplo, hacer que un método público sea privado.

El punto de herencia es que puede manejar al hijo como si fuera el padre. Si tiene una superclase 'Persona', una subclase 'Empleado', no tendría sentido que la clase Empleado no tenga el método de respiración ().

Al anular un método, es posible llamar a la implementación principal en algún momento durante la anulación, por lo tanto, al usar la anulación para agregar funcionalidad a la implementación principal.

No. En realidad, estaría aumentando la funcionalidad (de manera negativa)

Digamos que su nueva funcionalidad es "no hacer nada" pero el método, lo que ven los clientes de su código sigue siendo el mismo interface

No puede tener una subclase que elimine un método de su padre.

Esto es posible

class Parent {
    public void method_one(){ 
        print "Hello";
    }
}

class Child extends Parent {
     public void method_one(){
         // do nothing
     }
 }

Pero esto no es:

class Parent {
    public void method_one(){ 
        print "Hello";
    }
}

class Child extends Parent {
     // Attempt remove the method visibility, thus remove funcionality 
     private void method_one(){ 
         // do nothing
     }
 }

Y es por eso que anular (y en general, cualquier miembro virtual) es algo que debe hacerse con mucho cuidado ... De hecho, en general, al anular, debe intentar codificar tanto la clase base como la clase derivada, de modo que la implementación de la clase derivada primero llame a la implementación base y luego ejecute su funcionalidad adicional ...

pero este principio no se aplica en los lenguajes OO, y a menudo se viola ...

Ejemplo de por qué esto es malo

Imagine que tiene diseños de CompanyA Tipo (clase) Teléfono

namespace CompanyA {
   class Phone {
       public void Dial() {
        // do work to dial the phone here
       }
   }
}

No iagine Company B define otro tipo BetterPhone, que utiliza el teléfono de la empresa A como tipo base ...

namespace CompanyB {
   class BetterPhone: CompanyA.Phone {
       public void Dial()  {
           Console.WriteLine("BetterPhoneDial");
           EstablishConenction();
           base.Dial();
       }
   }
}

Ahora CompanyA, cuya clase de teléfono está en uso por otras compañías (Company C, D, etc.) decide que establecer una conexión es algo útil en la clase y modifica CompanyA.Phone, agregando una EsatblishCOnnection () método también, tal vez con una implementación diferente ... Hasta que tuvimos el " nuevo " palabra clave, este escenario habría roto la clase BetterPhone de CompanyB ... la primera vez que intentaron usar la nueva clase base.

Si su hijo requiere eliminar la funcionalidad del padre, entonces el padre debe declararse como Interfaz. Porque la interfaz es un mecanismo que define los contratos que debe cumplir su implementador.

Por ejemplo.


public interface IContract
{
  void DoWork();
}

public class BaseContract: IContract
{
 public virtual void DoWork()
 {
  //perform operation A
 }
}

Ahora, si desea declarar una nueva clase EnhancedContract, puede derivarla de BaseContract o IContract, según los requisitos. Si desea realizar una operación adicional a la operación A de base, puede heredarla de BaseContract como se muestra a continuación.


public class EnhancedContract: BaseContract
{
  public override void DoWork()
  {
   //perform operation B
   base.DoWork();
   //perform operation C
  }
}

Pero si no está interesado en realizar la operación A en el método DoWork de EnhancedContract, herede de IContract.

Esto asegura que EnhancedWork realizará DoWork (), pero no se garantiza que realice la 'operación A' en él.


public class EnhancedWork:IContract
{
  public void DoWork()
  {
   //perform operation D
  }
}

Esto es importante para comprender porque impedirá que el usuario realice la transmisión por debajo.


EnhancedContract e = new EnhancedContract();
BaseContract b = e;

Creo que todas estas operaciones son importantes al comprender Principio de Open Closed , Principio de sustitución de Liskov .

La regla de pulgar para la herencia es "Poner funcionalidad adicional en una existente".

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top