2010-04-27 25 views
19

¿Es posible en C# tener una clase que implemente una interfaz que tenga 10 métodos declarados pero que implemente solo 5 métodos, es decir, solo definir 5 métodos de esa interfaz? En realidad, tengo una interfaz que se implementa por 3 clases y no todos los métodos son utilizados por toda la clase, así que si pudiera excluir cualquier método ???Implementando algunos métodos de una clase de interfaz-C#

Necesito esto. Puede sonar como un mal diseño pero no es de esperar. Lo que pasa es que tengo una colección de controles de usuario que necesita tener una propiedad común y en base a eso solo los estoy mostrando en tiempo de ejecución. Como es dinámico, necesito administrarlos para eso estoy teniendo propiedades. Algunas propiedades son necesarias por pocas clases y no por todas. Y a medida que aumenta el control, es posible que estas propiedades estén aumentando, según lo necesite un control que necesito tener sin utilizar. solo los métodos simulados. Por lo mismo, pensé que si hubiera una manera de evitar esos métodos en el resto de la clase, sería genial. Suena que no hay otra manera que tiene o bien la clase abstracta o funciones simulados :-(

+15

Me parece que su interfaz no es lo suficientemente detallada, y debe aplicar el principio de segregación de la interfaz. –

+0

¿Por qué no hacer que las propiedades comunes formen parte de la interfaz y proporcionar una propiedad especial 'Diccionario' que obtenga todas las propiedades personalizadas para un control dado? ¿O por qué no usar interfaces adicionales separadas para cada tipo de control especial? De todos modos, tiene algún control de que el control admite esas propiedades personalizadas. Solo hazlo usando 'is ICustomControlKind42' o' como ICustomControlKind42' y cheque nulo. – SergGr

+0

@iPhone: ¿Pueden informar un poco más sobre esto? o puede mostrar algún enlace o ejemplo para el mismo ??? – Jankhana

Respuesta

23

Puede que sea una clase abstracta y añadir los métodos que no desea poner en práctica métodos como abstractos.

en otras palabras:

public interface IMyInterface 
{ 
    void SomeMethod(); 
    void SomeOtherMethod(); 
} 

public abstract class MyClass : IMyInterface 
{ 
    // Really implementing this 
    public void SomeMethod() 
    { 
     // ... 
    } 

    // Derived class must implement this 
    public abstract void SomeOtherMethod(); 
} 

Si todas estas clases tienen que ser concreto, no abstracto, entonces usted tiene que tirar un NotImplementedException/NotSupportedException desde el interior de los métodos Pero una idea mucho mejor sería dividir el. interfaz para que las clases de implementación no tengan que hacer esto.

Tenga en cuenta que las clases pueden implementar múltiples interfaces, por lo que si algunas clases tienen algunas de las funcionalidades, pero no todos, entonces usted quiere tener las interfaces más granulares:

public interface IFoo 
{ 
    void FooMethod(); 
} 

public interface IBar() 
{ 
    void BarMethod(); 
} 

public class SmallClass : IFoo 
{ 
    public void FooMethod() { ... } 
} 

public class BigClass : IFoo, IBar 
{ 
    public void FooMethod() { ... } 
    public void BarMethod() { ... } 
} 

Este es probablemente el diseño que realmente debería tener.

+1

Creo que esta es la respuesta correcta a la pregunta incorrecta. Creo que el verdadero problema es el mal diseño de la interfaz. Si algunas clases no implementan algunos métodos de interfaz, significa que necesita más de una interfaz. Y las clases implementarán solo aquellas interfaces que sean necesarias para ellos – SergGr

+0

FWIW Yo diría que SomeMethod debería ser virtual. –

+0

iPhone: No necesariamente. La interfaz ICollection <> define los métodos Agregar y Eliminar, pero es común no implementarlos para las colecciones de solo lectura. Pero sí, en general, tengo que estar de acuerdo contigo. –

2

Simplemente puede tener los métodos que no desea implementar trow a 'NotImplementedException'. De esa forma, todavía puedes implementar la interfaz de la forma habitual.

+0

No puedo usar 'NotImplementedException' ya que la excepción será arrojada a mi código que no lo sé y va en contra de mi requerimiento así que :-( – Jankhana

+0

En ese caso contesté la respuesta de PoweRoy – UpTheCreek

2

Eso no es posible. Pero lo que puede hacer es lanzar NotSupportedException o NotImplementedException para los métodos que no desea implementar. O podrías usar una clase abstracta en lugar de una interfaz. De esta forma, podría proporcionar una implementación predeterminada para los métodos que elija no anular.

public interface IMyInterface 
{ 
    void Foo(); 

    void Bar(); 
} 

public class MyClass : IMyInterface 
{ 
    public void Foo() 
    { 
    Console.WriteLine("Foo"); 
    } 

    public void Bar() 
    { 
    throw new NotSupportedException(); 
    } 
} 

O ...

public abstract class MyBaseClass 
{ 
    public virtual void Foo() 
    { 
    Console.WriteLine("MyBaseClass.Foo"); 
    } 

    public virtual void Bar() 
    { 
    throw new NotImplementedException(); 
    } 
} 

public class MyClass : MyBaseClass 
{ 
    public override void Foo() 
    { 
    Console.WriteLine("MyClass.Foo"); 
    } 
} 
+3

Además, si no quiere, no métodos implementados para ser visible en Intellisense puede implementar explícitamente Por ejemplo: public class MiClase:. IMyInterface { ... IMyInterface.MyNotImplementedMethod public void() { tiro nueva NotImplementedException();} } de esta manera si tiene una variable de tipo MyClass, los métodos explícitamente implementados no se mostrarán en Intellisen se. – Anero

+0

Hmmm eso significa que MyInterface.MyNotImplementedMethod() será visible ??? – Jankhana

+0

Sí, los métodos explícitamente implementados no serán visibles si tiene un objeto como referencia para dicha clase. Si lo tiene como referencia a la interfaz, ellos, por supuesto, serán visibles. – SergGr

0

deje que su interfaz implementarse en una clase abstracta. La clase abstracta implementará 5 métodos y mantendrá los métodos restantes como virtuales. Todas sus 3 clases deberían heredar de la clase abstracta. Este era su código de cliente que usa 3 clases no tendrá que cambiar.

16

Su ruptura del uso de interfaces. Debería tener para cada comportamiento común una interfaz separada.

1

No, no lo es. Debe definir todos los métodos de la interfaz, pero puede definirlos como abstractos y dejar la implementación en cualquier clase derivada. No puede compilar una clase que dice que implementa una interfaz cuando en realidad no lo hace.

2

Si bien estoy de acuerdo con @PoweRoy, es probable que necesite dividir su interfaz en partes más pequeñas, probablemente pueda utilizar interfaces explícitas para proporcionar una API pública más limpia a sus implementaciones de interfaz.

Ej:

public interface IPet 
{ 
    void Scratch(); 
    void Bark(); 
    void Meow(); 
} 

public class Cat : IPet 
{ 
    public void Scratch() 
    { 
     Console.WriteLine("Wreck furniture!"); 
    } 

    public void Meow() 
    { 
     Console.WriteLine("Mew mew mew!"); 
    } 

    void IPet.Bark() 
    { 
     throw NotSupportedException("Cats don't bark!"); 
    } 
} 

public class Dog : IPet 
{ 
    public void Scratch() 
    { 
     Console.WriteLine("Wreck furniture!"); 
    } 

    void IPet.Meow() 
    { 
     throw new NotSupportedException("Dogs don't meow!"); 
    } 

    public void Bark() 
    { 
     Console.WriteLine("Woof! Woof!"); 
    } 
} 

Con las clases definidas anteriormente:

var cat = new Cat(); 
cat.Scrach(); 
cat.Meow(); 
cat.Bark(); // Does not compile 


var dog = new Dog(); 
dog.Scratch(); 
dog.Bark(); 
dog.Meow(); // Does not compile. 


IPet pet = new Dog(); 
pet.Scratch(); 
pet.Bark(); 
pet.Meow(); // Compiles but throws a NotSupportedException at runtime. 

// Note that the following also compiles but will 
// throw NotSupportedException at runtime. 
((IPet)cat).Bark(); 
((IPet)dog).Meow(); 
+0

Este es un ejemplo muy apropiado ya que Cow no puede ladrar y el perro no puede maullar pero aún no puedo segregar la interfaz hmmm :-( – Jankhana

0

Quiero añadir dinámicamente el control a mi forma como lo he hecho eso como requisito. Encontré el código de here. Lo edité como lo necesitaba. Entonces tengo la clase IService que tiene las propiedades comunes. Esto es implementado por los controles de usuario. Que se muestran en tiempo de ejecución en proyectos diferentes. Hmmm, tengo una interfaz común diferente que tiene propiedades que el proyecto utiliza para mostrar los controles. Pocos controles necesitan algunos métodos o propiedades adicionales, por ejemplo, para implementar un menú contextual basado en la selección del usuario en el tiempo de ejecución. es decir, los valores están ahí en el proyecto que se pasarán como propiedades al control y se mostrarán. Ahora que este menú está ahí solo para un control, el resto de ellos no tiene esto. Así que pensé que si había una manera de no tener esos métodos en toda la clase en lugar de una sola clase. Pero parece que necesito ir a los métodos ficticios oa la clase abstracta. hmmm los métodos ficticios serían más preferibles para mí que la clase abstracta :-(

1

Aquí hay un ejemplo estúpido simple de lo que quiero decir con diferentes interfaces para diferentes propósitos. No hay interfaz para propiedades comunes, ya que complicaría el ejemplo. También este código carece de muchas otras cosas buenas (como el diseño de suspensión) para que quede más claro. No he intentado compilar este código, así que podría haber muchos errores tipográficos, pero espero que la idea sea clara.

+0

Intentaré usar esto. Gracias. Así que concluí que necesito tener los métodos ficticios o la clase abstracta con funciones virtuales. Preferiría ir con métodos ficticios que tener una clase abstracta. Gracias por toda tu respuesta. Aprendí muchas cosas nuevas. – Jankhana

+0

No, de esta manera no tienes que tener métodos ficticios. Necesitas varios tipos diferentes. Puede agregar otras interfaces para funciones diferentes y verificarlas de la misma manera. Cada control implementará solo aquellas interfaces que requiera el control. – SergGr

0

Al implementar uno de los principios SÓLIDOS que es el "Principio de segregación de interfaz" en el que la interfaz está dividida en varias interfaces.

0

Además de las excelentes sugerencias anteriores sobre el diseño de interfaces, si realmente necesita implementar algunos de los métodos, una opción es usar 'Métodos de extensión'. Mueva los métodos que necesitan implementación fuera de su interfaz. Cree otra clase estática que implemente estos como métodos estáticos con el primer parámetro como 'este interfaceObject'. Esto es similar a los métodos de extensión utilizados en LINQ para la interfaz IEnumerable.

public static class myExtension { 
    public static void myMethod(this ImyInterface obj, ...) { .. } 
... 
} 
Cuestiones relacionadas