InicioArticulos y noticiasBases de datosProgramaciónForosInternetServiciosContratacionEmail
Tutorial C#
Introduccion a C#
Programacion con C#
Fundamentos de C#
Operadores
Instrucciones
Estrcuturas de control.
Definición de clases
Creación de objetos
Herencia y métodos virtuales
Polimorfismo
Ocultación de miembros
Miembros de tipo
Encapsulación
Espacios de nombres
Importación de espacios de nombres
Espacio de nombres distribuidos
Variables y tipos de datos
Tablas unidimensionales
Tablas multidimensionales
La clase System.Array
Cadenas de texto
Constantes
Orden de inicialización de variables
Métodos
Métodos externos
Constructores
Destructores
Propiedades
Indizadores
Redefinición de operadores
Delegados y eventos
La clase MulticastDelegate
Llamadas asíncronas
Implementación interna de los delegados
Eventos
Estructuras
Boxing y unboxing
Constructores de estructuras
Enumeraciones
Interfaces
Excepciones
Otras instrucciones
Atributos
Definición de nuevos atributos
Lectura de atributos en tiempo de ejecución
Atributos de compilación
Pseudoatributos
Código inseguro
Definición de punteros
Manipulación de punteros
Operadores relacionados con código inseguro
Fijación de variables apuntadas
Novedades de C# 2.0
Genéricos
Tipos parciales
Iteradores
Mejoras en la manipulación de delegados
Tipos anulables
Modificadores de visibilidad de bloques get y set
Clases estáticas
Referencias a espacios de nombres
Supresión temporal de avisos
Atributos condicionales
Incrustación de tablas en estructuras
Modificaciones en el compilador
También puedes ver ...
SubVersion y Visual Studio
Encriptación con AES Rijndael - Ejemplo
TripleDES - Un ejemplo practico en C#
Insertar una marca de agua en documentos PDF
Serialización: XmlSerializer y BinaryFormater
Handler para manipular imagenes
Conversiones de tipos personalizadas (VB y C#)
Compresión por gzip y deflate
La página Web que está abriendo contiene tanto elementos seguros como no seguros.
Cómo insertar un fichero .xml en un campo de tipo XML de SQL server 2005 o 2008


Interfaces

Concepto de interfaz

    Una interfaz es la definición de un conjunto de métodos para los que no se da implementación, sino que se les define de manera similar a como se definen los métodos abstractos. Es más, una interfaz puede verse como una forma especial de definir clases abstractas que tan sólo contengan miembros abstractos.

    Como las clases abstractas, las interfaces son tipos referencia, no puede crearse objetos de ellas sino sólo de tipos que deriven de ellas, y participan del polimorfismo. Sin embargo, también tienen numerosas diferencias con éstas:

  • Es posible definir tipos que deriven de más de una interfaz. Esto se debe a que los problemas que se podrían presentar al crear tipos que hereden de varios padres se deben a la difícil resolución de los conflictos derivados de la herencia de varias implementaciones diferentes de un mismo método. Sin embargo, como con las interfaces esto nunca podrá ocurrir en tanto que no incluyen código, se permite la herencia múltiple de las mismas.

  • Las estructuras no pueden heredar de clases pero sí de interfaces, y las interfaces no pueden derivar de clases, pero sí de otras interfaces.

  • Todo tipo que derive de una interfaz ha de dar una implementación de todos los miembros que hereda de esta, y no como ocurre con las clases abstractas donde es posible no darla si se define como abstracta también la clase hija. De esta manera queda definido un contrato en la clase que la hereda que va a permitir poder usarla con seguridad en situaciones polimórficas: toda clase que herede una interfaz implementará todos los métodos de la misma. Por esta razón se suele denominar implementar una interfaz al hecho de heredar de ella.

    Nótese que debido a esto, no suele convenir ampliar interfaces ya definidas e implementadas, puesto que cualquier añadido invalidará sus implementaciones hasta que se defina en las mismas un implementación para dicho añadido. Sin embargo, si se hereda de una clase abstracta este problema no se tendrá siempre que el miembro añadido a la clase abstracta no sea abstracto.

  • Las interfaces sólo pueden tener como miembros métodos normales, eventos, propiedades e indizadores; pero no pueden incluir definiciones de campos, operadores, constructores, destructores o miembros estáticos. Además, todos los miembros de las interfaces son implícitamente públicos y no se les puede dar ningún modificador de acceso (ni siquiera public, pues se supone)

Definición de interfaces

    La sintaxis general que se sigue a la hora de definir una interfaz es:


<modificadores> interface <nombre>:<interfacesBase>
{
 <miembros>
}

    Los <modificadores> admitidos por las interfaces son los mismos que los de las clases Es decir, public, internal, private, protected, protected internal o new (e igualmente, los cuatro últimos sólo son aplicables a interfaces definidas dentro de otros tipos)

    El <nombre> de una interfaz puede ser cualquier identificador válido, aunque por convenio se suele usar I como primer carácter del mismo (IComparable, IA, etc)

    Los <miembros> de las interfaces pueden ser definiciones de métodos, propiedades,  indizadores o eventos, pero no campos, operadores, constructores o destructores. La sintaxis que se sigue para definir cada tipo de miembro es la misma que para definirlos como abstractos en una clase pero sin incluir abstract por suponerse implícitamente:

  • Métodos: <tipoRetorno> <nombreMétodo>(<parámetros>);

  • Propiedades: <tipo> <nombrePropiedad> {set; get;}

    Los bloques get y set pueden intercambiarse y puede no incluirse uno de ellos (propiedad de sólo lectura o de sólo escritura según el caso), pero no los dos.

  • Indizadores: <tipo> this[<índices>] {set; get;}

    Al igual que las propiedades, los bloques set y get pueden intercambiarse y obviarse uno de ellos al definirlos.

  • Eventos: event <delegado> <nombreEvento>;

    Nótese que a diferencia de las propiedades e indizadores, no es necesario indicar nada sobre sus bloques add y remove. Esto se debe a que siempre se han de implementar ambos, aunque si se usa la sintaxis básica el compilador les da una implementación por defecto automáticamente.

    Cualquier definición de un miembro de una interfaz puede incluir el modificador new para indicar que pretende ocultar otra heredada de alguna interfaz padre. Sin embargo, el resto de modificadores no son válidos ya que implícitamente siempre se considera que son public y abstract. Además, una interfaz tampoco puede incluir miembros de tipo, por lo que es incorrecto incluir el modificador static al definir sus miembros.

    Cada interfaz puede heredar de varias interfaces, que se indicarían en <interfacesBase> separadas por comas. Esta lista sólo puede incluir interfaces, pero no clases o estructuras; y a continuación se muestra un ejemplo de cómo definir una interfaz IC que hereda de otras dos interfaces IA y IB:


public delegate void D (int x);
interface IA
{
 int PropiedadA{get;}
 void Común(int x);
}
interface IB
{
 int this [int índice] {get; set;}
 void Común(int x);
}
interface IC: IA, IB
{
 event D EventoC;
}

    Nótese que aunque las interfaces padres de IC contienen un método común no hay problema alguno a la hora de definirlas. En el siguiente epígrafe veremos cómo se resuelven las ambigüedades que por esto pudiesen darse al implementar IC.

Implementación de interfaces

    Para definir una clase o estructura que implemente una o más interfaces basta incluir los nombres de las mismas como si de una clase base se tratase -separándolas con comas si son varias o si la clase definida hereda de otra clase- y asegurar que la clase cuente con definiciones para todos los miembros de las interfaces de las que hereda -lo que se puede conseguir definiéndolos en ella o heredándolos de su clase padre.

    Las definiciones que se den de miembros de interfaces han de ser siempre públicas y no pueden incluir override, pues como sus miembros son implícitamente abstract se sobreentiende. Sin embargo, sí pueden dársele los modificadores como virtual ó abstract y usar override en redefiniciones que se les den en clases hijas de la clase que implemente la interfaz.

    Cuando una clase deriva de más de una interfaz que incluye un mismo miembro, la implementación que se le dé servirá para todas las interfaces que cuenten con ese miembro. Sin embargo, también es posible dar una implementación diferente para cada una usando una implementación explícita, lo que consiste en implementar el miembro sin el modificador public y anteponiendo a su nombre el nombre de la interfaz a la que pertenece seguido de un punto (carácter .)

    Cuando un miembro se implementa explícitamente, no se le pueden dar modificadores como en las implementaciones implícitas, ni siquiera virtual o abstract. Una forma de simular los modificadores que se necesiten consiste en darles un cuerpo que lo que haga sea llamar a otra función que sí cuente con esos modificadores.

    El siguiente ejemplo muestra cómo definir una clase CL que implemente la interfaz IC:


class CL:IC
{
 public int PropiedadA    
 {
  get {return  5;}
  set {Console.WriteLine("Asignado{0} a PropiedadA", value);}
 }
 
 void IA.Común(int x)
 {
  Console.WriteLine("Ejecutado Común() de IA");
 }
 
 public int this[int índice]
 {
  get { return 1;}
  set { Console.WriteLine("Asignado {0} a indizador", value); }
 }
 
 void IB.Común(int x)
 {
  Console.WriteLine("Ejecutado Común() de IB");
 }
 
 public event D EventoC;
}
           
    Como se ve, para implementar la interfaz IC ha sido necesario implementar todos sus miembros, incluso los heredados de IA y IB, de la siguiente manera:

  • Al EventoC se le ha dado la implementación por defecto, aunque si se quisiese se podría haber dado una implementación específica a sus bloques add y remove.

  • Al método Común() se le ha dado una implementación para cada versión heredada de una de las clases padre de IC, usándose para ello la sintaxis de implementación explícita antes comentada. Nótese que no se ha incluido el modificador public en la implementación de estos miembros.

  • A la PropiedadA se le ha dado una implementación con un bloque set que no aparecía en la definición de PropiedadA en la interfaz IA. Esto es válido hacerlo siempre y cuando la propiedad no se haya implementado explícitamente, y lo mismo ocurre con los indizadores y en los casos en que en vez de set sea get el bloque extra implementado.

    Otra utilidad de las implementaciones explícitas es que son la única manera de conseguir poder dar implementación a métodos ocultados en las definiciones de interfaces. Por ejemplo, si tenemos:


interface IPadre
{
 int P{get;}
}
interface IHija:Padre
{
 new int P();
}

    La única forma de poder definir una clase donde se dé una implementación tanto para el método P() como para la propiedad P, es usando implementación explícita así:


class C: IHija
{
 void IPadre.P {}
 public int P() {…}
}

O así:


class C: IHija
{
 public void P() {}
 int IHija.P() {}
}

O así:


class C: IHija
{
 void IPadre.P() {}
 int IHija.P() {}
}

    Pero como no se puede implementar es sin ninguna implementación explícita, pues se  produciría un error al tener ambos miembros las misma signatura. Es decir, la siguiente definición no es correcta:


class C: IHija
{
 public int P() {} // ERROR: Ambos miembros tienen la misma signatura
 public void P(){}
}

    Es posible reimplementar en una clase hija las definiciones que su clase padre diese para los métodos que heredó de una interfaz. Para hacer eso basta hacer que la clase hija también herede de esa interfaz y dar en ella las definiciones explícitas de miembros de la  interfaz que se estimen convenientes, considerándose que las implementaciones para los demás serán las heredadas de su clase padre. Por ejemplo:


 using System;
 
 interface IA
 {
  void F();
 }
 
 class C1: IA
 {
  public void F()
  {
   Console.WriteLine("El F() de C1");
  }
 }
 
 class C2: C1, IA
 {// Sin implementación explícita no redefiniría, sino ocultaría
  void IA.F()   
{
   Console.WriteLine("El F() de C2");
  }
  
  public static void Main()
  {
   IA obj = new  C1();
   IA obj2 = new C2();
   obj.F();
   obj2.F();
  }  
 

    Reimplementar un  miembro de una interfaz de esta manera es parecido a redefinir los miembros reimplementados, sólo que ahora la redefinición sería solamente accesible a través de variables del tipo de la  interfaz. Así, la salida del ejemplo anterior sería:

 

 El F() de C1

 El F() de C2

 

    Hay que tener en cuenta que de esta manera sólo pueden hacerse reimplementaciones de miembros si la clase donde se reimplementa hereda directamente de la interfaz implementada explícitamente o de alguna interfaz derivada de ésta. Así, en el ejemplo anterior sería incorrecto haber hecho:

 
 class C2:C1 //La lista de herencias e interfaces implementadas por C2 sólo incluye a C1
 {
  void IA.f();    // ERROR: Aunque C1 herede de IA, IA no se incluye directamente
                  // en la lista de interfaces implementadas por C2
 }

     Es importante señalar que el nombre de interfaz especificado en una implementación explícita ha de ser exactamente el nombre de la interfaz donde se definió el miembro implementado, no el de alguna subclase de la misma. Por ejemplo:


interface I1
{
 void F()
}
interface I2:I1 
{}
class C1:I2
{
 public void I2.F();  //ERROR: habría que usar I1.F()
}

    En el ejemplo anterior, la línea comentada contiene un error debido a que F() se definió dentro de la interfaz I1, y aunque también pertenezca a I2 porque ésta lo hereda de I1, a la hora de implementarlo explícitamente hay que prefijar su nombre de I1, no de I2.

Acceso a miembros de una interfaz

    Se puede acceder a los miembros de una interfaz implementados en una clase de manera no explícita a través de variables de esa clase como si de miembros normales de la misma se tratase. Por ejemplo, este código mostraría un cinco por pantalla:


CL c = new CL();
Console.WriteLine(c.PropiedadA);

    Sin embargo, también es posible definir variables cuyo tipo sea una interfaz. Aunque no existen constructores de interfaces, estas variables pueden inicializarse gracias al polimorfismo asignándoles objetos de clases que implementen esa interfaz. Así, el siguiente código también mostraría un cinco por pantalla:


IA a = new CL();
Console.WriteLine(a.PropiedadA);

     Nótese que a través de una variable de un tipo interfaz sólo se puede acceder a miembros del objeto almacenado en ella que estén definidos en esa interfaz. Es decir, los únicos miembros válidos para el objeto a anterior serían PropiedadA y Común()

    En caso de que el miembro al que se pretenda acceder haya sido implementado  explícitamente, sólo puede accederse a él a través de variables del tipo interfaz al que pertenece y no a través de variables de tipos que hereden de ella, ya que la definición de estos miembros es privada al no llevar modificador de acceso. Por ejemplo:


CL cl = new CL();
IA a = cl;
IB b = cl;
// Console.WriteLine(cl.Común());  // Error: Común()
// fue implementado explícitamente
Console.WriteLine(a.Común());  
Console.WriteLine(b.Común());
Console.WriteLine(((IA) cl).Común());     
Console.WriteLine(((IB) cl).Común());     

    Cada vez que se llame a un método implementado explícitamente se llamará a la versión del mismo definida para la interfaz a través de la que se accede. Por ello, la salida del código anterior será:


 Ejecutado Común() de IA

 Ejecutado Común() de IB

 Ejecutado Común() de IA

 Ejecutado Común() de IB 

    Se puede dar tanto una implementación implícita como una explícita de cada miembro de una interfaz. La explícita se usará cuando se acceda a un objeto que implemente esa interfaz a través de una referencia a la interfaz, mientras que la implícita se usará cuando el acceso se haga a través de una referencia del tipo que implementa la interfaz. Por ejemplo, dado el siguiente código:


interface I
{object Clone();}
class Clase:I
{
 public object Clone()
 {
  Console.WriteLine("Implementación implícita");
 }
 public object IClonable.Clone()
 {
  Console.WriteLine("Implementación explícita");
 }
 
 public static void Main()
 {
  Clase obj = new Clase();
  ((I) obj).Clone();
  obj.Clone();      
 }
}

     El resultado que por pantalla se mostrará tras ejecutarlo es:

 Implementación explícita

 Implementación implícita

Acceso a miembros de interfaces y boxing

Es importante señalar que aunque las estructuras puedan implementar interfaces tal y como lo hacen las clases, el llamarlas a través de referencias a la interfaz supone una gran pérdida de rendimiento, ya que como las interfaces son tipos referencia ello implicaría la realización del ya visto proceso de boxing. Por ejemplo, en el código:


 using System;
 
 interface IIncrementable
 { void Incrementar();}
 
 struct Estructura:IIncrementable
 {
  public int Valor;
  
  public void Incrementar()
  {
   Valor++;
  }
  
  static void Main()
  {
   Estructura o = new Estructura();
   Console.WriteLine(o.Valor);
   ((IIncrementable) o).Incrementar();
   Console.WriteLine(o.Valor);
   o.Incrementar();
   Console.WriteLine(o.Valor);
  }
 }

    La salida obtenida será:


 0

 0

 1 

    Donde nótese que el resultado tras la primera llamada a Incrementar() sigue siendo el mismo ya que como se le ha hecho a través de un referencia a la interfaz, habrá sido aplicado sobre la copia de la estructura resultante del boxing y no sobre la estructura original. Sin embargo, la segunda llamada sí que se aplica a la estructura ya que se realiza directamente sobre el objeto original, y por tanto incrementa su campo Valor.


Inicio | Tutorial C# EnumeracionesTutorial C#Excepciones Versión para imprimir Foros de consulta

 
fuck fuck fuck... por Anónimo
Respuesta recibida el [17/09/2007 11:32:09]
fuck fuck fuck

 
Genial por Anónimo
Respuesta recibida el [11/12/2007 07:00:16]
Estupendo!!! Al fin una página que realmente me ha aclarado el tema de las interfaces de forma que lo he podido entender.
Gracias y felicidades por la página

 
Codigo por Anon
Respuesta recibida el [01/07/2008 05:20:53]
Creo que el codigo necesita algunos ajustes por que no jala out of the box, y siendo un tutorial para iniciarse con interfaces, es muy importante que el codigo jale bien para entenderlo

 
public delegate void D (int x)... por Anónimo
Respuesta recibida el [05/12/2008 06:23:54]
public delegate void D (int x);
interface IA{ int PropiedadA{get;} void Común(int x);}
interface IB{ int this [int índice] {get; set;} void Común(int x);}
interface IC: IA, IB{ event D EventoC; }

 
Herencia e interfaz al mismo tiempo por Anónimo
Respuesta recibida el [29/01/2009 06:00:14]
es posible implementar una interfaz y heredar de una clase al mismo tiempo???

 
Para Anónimo por Popeye
Respuesta recibida el [01/02/2009 04:43:22]
En respuesta al último mensaje, sí que se puede.

Nombreclase:Clasebase, Interfaz1, Interfaz2, Interfaz3

 
excelente! por alfred
Respuesta recibida el [03/04/2009 07:46:09]
Definitivamente hay gente muy desocupada que entra a criticar y ridiculizar este excelente trabajo. Mil gracias por el trabajo tomado y excelente la página. Saludos!

 
Una vez mas agradezco este est... por Netsky
Respuesta recibida el [26/04/2009 06:39:19]
Una vez mas agradezco este estupendo trabajao, la unica forma de que expliquen todo esto es leer la documentacion de .NEt, porque en libros jamas te diran todo lo que aqui explican  y profesores ni se diga... 
Gracias..

 
GRacias por The Lonches
Respuesta recibida el [12/05/2009 07:25:52]
muy bueno, Espero mas gracias

 
caracteristicas de v.net por diblis
Respuesta recibida el [28/05/2009 12:58:01]
muy buena pagina si es posible, alguien sabe a que se refieren las caracteristicas de visual.net tales como: interfaces, miembros compartidos,ensamblados,delegados,referencias,espacios de nombres,atributos,subprocesamiento multiple. Si me pueden ayudar se los agradeceria mucho ya que estoy por iniciar la programacion en .net y es un trabajo que tengo que entregar

 
Excelente Tema por Raul
Respuesta recibida el [20/12/2009 09:49:11]
Excelente la explicacion del tema, par a mi que estoy recien aprendiendo estas cosas, me ha aclarado muchas dudas... gracias... y felicitaciones por este trabajo

 
y si quiero algo como... (el ... por Anónimo
Respuesta recibida el [13/01/2010 11:07:31]
y si quiero algo como...
(el que haga o no sentido no importa... se puede o no?)

interface iAlgo{
bool Revisar();
}

clase cBase() : iAlgo
{
funcion(){
Revisar();
}
bool Revisar(){
return true;
}
}


Añadir comentario ... Para preguntar utiliza los foros
Autor:

Título:


Para preguntar utiliza los foros.



Inicio | Tutorial C# EnumeracionesTutorial C#Excepciones Versión para imprimir

Interfaces
Autor: José Antonio González Seco
Visitas: 29107 Fecha de publicación: 09/11/2006
José Antonio es experto en tecnologias Microsoft. Imparte cursos y conferencias en congresos sobre C# y .NET en Universidades de toda España (Sevilla, Barcelona, San Sebastián, Valencia, Oviedo, etc.) en representación de grandes empresas como Microsoft.




Visitas: 86 | Comentarios: 2 | Archivo: Articulos
02/02/2010 iPad vs Telesketch
Visitas: 791 | Comentarios: 2 | Archivo: Articulos
Categorias: Humor
Visitas: 739 | Comentarios: 3 | Archivo: Articulos
Visitas: 3134 | Comentarios: 2 | Archivo: Articulos
Categorias: C#
Visitas: 14487 | Comentarios: 7 | Archivo: Articulos
Categorias: C#|Seguridad
Visitas: 1474 | Comentarios: 3 | Archivo: Articulos
Visitas: 690 | Comentarios: 2 | Archivo: Articulos
Visitas: 368 | Comentarios: 0 | Archivo: Articulos
Visitas: 2006 | Comentarios: 2 | Archivo: Articulos
Categorias: C#

Útimos temas recibidos en los foros ...
certificado pensiones horizonte por angela patricia rodriguez ... [Actualidad] 135 26/01/2010
pensiones por eduard ... [Visual Basic 6.0] 0 11/03/2010
Manual Visual Studio.NET por Shiko ... [Visual Basic .NET] 41 26/10/2006
cap de setmana genial por ramón ... [Java] 0 11/03/2010
cetificado de pension por RICARDDO RAFAEL SOLANO ORZCO ... [Actualidad] 0 11/03/2010
solicitud de aifiliacion a porvernir por julios ... [Actualidad] 2 11/03/2010
Solicitar el certificado de pensiones de Abelardo Alfonso Serrano Banegas C.C. 18 971 771 de Curumani Cesar por Marta ... [Actualidad] 0 11/03/2010
Solicitud certificado de afiliaciones a pensiones y cesantias proteccion por hz ... [Actualidad] 50 10/02/2010
cerificado fondo horizonte de pensiones y cesantias por carlos fideligno torres herrera ... [Actualidad] 146 18/01/2010
certificado de afiliación de pensiones y cesantias por secre ... [Actualidad] 109 28/01/2010
certificado de fondos de pensiones horizonte por mona ... [Actualidad] 5 03/03/2010
Certificado de afiliacion AFP (PENSIONES) Horizonte por Sandris ... [Actualidad] 68 30/01/2010

Access CGI JSP ORACLE UNIX
Actualidad HTML/DHTML/XHTML LINUX PHP Visual Basic .NET
ASP ISAPI MS DOS Power Builder Visual Basic 6.0
ASP.NET Java mySQL SQL WIN 98/NT/2000/XP
C# JavaScript Opinion SQL Server

devjoker  Te recomendamos además ...
22/10/2005 Insertar datos. INSERT    forma parte de...Tutorial SQL
16/04/2004 C# y como crear instancias de clases desde un tipo String utilizando .NET FrameWork.
21/07/2006 Funciones integradas de PL/SQL    forma parte de...Tutorial PL/SQL
09/05/2006 Como leer XML con C#
22/10/2005 Actualización de datos. UPDATE    forma parte de...Tutorial SQL
03/10/2006 Fundamentos de C#    forma parte de...Tutorial C#
05/07/2007 Consultar datos en Transact SQL    forma parte de...Tutorial de Transact SQL
12/01/2006 Introducción a PLSQL    forma parte de...Tutorial PL/SQL
19/10/2006 Llamadas asíncronas    forma parte de...Tutorial C#
14/07/2006 Tablas PL/SQL    forma parte de...Tutorial PL/SQL

 

Encuesta
¿A que perfil te adaptas mejor?




[Ver] [Votar]