Beruflich Dokumente
Kultur Dokumente
Contenido
Descripcin general
Derivacin de clases
1
3
Implementacin de mtodos
11
22
Uso de interfaces
24
31
Herencia en C#
Herencia en C#
Descripcin general
Objetivo del tema
Explicacin previa
En este mdulo
estudiaremos la herencia de
clases en C#.
Derivacin de clases
Implementacin de mtodos
Uso de interfaces
Herencia en C#
Herencia en C#
Derivacin de clases
Objetivo del tema
Explicacin previa
En esta seccin
discutiremos cmo derivar
una clase de una clase
base.
Slo es posible derivar una clase a partir de una clase base si sta ha sido
diseada para permitir la herencia. Esto se debe a que los objetos deben tener la
estructura adecuada, ya que de lo contrario la herencia no resultar eficaz. Este
hecho tiene que quedar claro en una clase base que est diseada para herencia.
Si se deriva una nueva clase de una clase base que no est bien diseada,
cualquier cambio futuro en la clase base podra hacer que la clase derivada
fuese inutilizable.
Al final de esta leccin, usted ser capaz de:
Derivar una clase nueva a partir de una clase base.
Acceder a los miembros y constructores de la clase base desde la clase
derivada.
Herencia en C#
Explicar el procedimiento
para extender una clase
base.
Explicacin previa
class
class Token
Token
Clase
Clase
{{
Clasederivada
derivada
Clasebase
base
...
...
}}
class
class ComentToken:
ComentToken: Token
Token
{{
22puntos
...
puntos
...
}}
Token
Token
concrete
concrete
ComentToken
ComentToken
concrete
concrete
La derivacin de una clase desde una clase base se conoce tambin como
extensin de la clase base. Una clase C# se puede extender como mximo una
clase.
Herencia en C#
La sintaxis de C# para derivar una clase de otra tambin est permitida en C++,
donde indica implcitamente una relacin de herencia privada a entre la clase
base y la derivada. C# no incluye herencia privada; toda la herencia es pblica.
Herencia en C#
Explicacin previa
class
class Token
Token
{{ ...
class
...
class Outside
Outside
protected
string
name;
{
protected string name; {
}}
void
void Fails(Token
Fails(Token t)
t)
class
ComentToken:
Token
{
class ComentToken: Token
{
{{ ...
...
...
...
public
string
Name(
)
t.name
public string Name( )
t.name
{{
...
...
return
name;
}
return name;
}
}}
}}
}}
Herencia en C#
Herencia en C#
Explicacin previa
class
class Token
Token
{{
protected
protected Token(string
Token(string name)
name) {{ ...
... }}
...
...
}}
class
class ComentToken:
ComentToken: Token
Token
{{
public
public ComentToken(string
ComentToken(string name)
name) :: base(name)
base(name) {{ }}
...
...
}}
Declaraciones de constructores
Si la clase derivada no hace una llamada explcita a un constructor de la clase
base, el compilador de C# usar implcitamente un inicializador de constructor
de la forma :base( ). Esto implica que una declaracin de constructor de la
forma
C(...) {...}
es equivalente a
C(...): base( ) {...}
Herencia en C#
En este caso, es imposible que una clase derivada pueda hacer una llamada al
constructor de la clase base.
Herencia en C#
10
mbito de un identificador
Tambin es posible utilizar la palabra reservada base para habilitar el mbito de
un identificador. Esto puede resultar til, puesto que una clase derivada puede
declarar miembros con los mismos nombres que miembros de la clase base. El
siguiente cdigo muestra un ejemplo:
class Token
{
protected string name;
}
class ComentToken: Token
{
public void Method(string name)
{
base. name = name;
}
}
Herencia en C#
11
Implementacin de mtodos
Objetivo del tema
Explicacin previa
Los mtodos de una clase base se pueden redefinir en una clase derivada si han
sido diseados para permitir la sustitucin (override).
Al final de esta leccin, usted ser capaz de:
Usar el tipo de mtodo virtual.
Usar el tipo de mtodo override.
Usar el tipo de mtodo hide.
Herencia en C#
12
Explicacin previa
class
class Token
Token
{{
...
...
public
public int
int LineNumber(
LineNumber( ))
{{ ...
...
}}
public
public virtual
virtual string
string Name(
Name( ))
{{ ...
...
}}
}}
El ejercicio de la prctica
combinar el contenido de
los tres temas sobre las
palabras reservadas virtual,
override y new.
Herencia en C#
13
Explicacin previa
Para usar eficazmente los mtodos virtuales hay que tener en cuenta lo
siguiente:
No se puede declarar mtodos virtuales como estticos.
Los mtodos virtuales no pueden ser estticos porque en ese caso seran
mtodos de clase y el polimorfismo se aplica a objetos, no a clases.
No se puede declarar mtodos virtuales como privados.
Los mtodos virtuales no pueden ser privados porque en ese caso no podran
ser sustituidos por polimorfismo en una clase derivada. A continuacin se
muestra un ejemplo:
class Token
{
private virtual string Name( ) { ... }
// Error al compilar
}
Herencia en C#
14
Explicacin previa
class
class Token
Token
{{ ...
...
public
public virtual
virtual string
string Name(
Name( )) {{ ...
... }}
}}
class
class ComentToken:
ComentToken: Token
Token
{{ ...
...
public
public override
override string
string Name(
Name( )) {{ ...
... }}
}}
Como ocurre con los mtodos virtuales, un mtodo override debe contener un
cuerpo cuando se declara, ya que de lo contrario el compilador genera un error:
class Token
{
public virtual string Name( ) { ... }
}
class ComentToken: Token
{
public override string Nombre( ); // Error al compilar
}
Herencia en C#
15
Explicacin previa
class
class Token
Token
{{ ...
...
public
public int
int LineNumber(
LineNumber( )) {{ ...
... }}
public
public virtual
virtual string
string Name(
Name( )) {{ ...
... }}
}}
class
class ComentToken:
ComentToken: Token
Token
{{ ...
...
public
public override
override int
int LineNumber(
LineNumber( )) {{ ...
... }}
public
public override
override string
string Name(
Name( )) {{ ...
... }}
}}
8
9
Para usar eficazmente los mtodos override hay que tener en cuenta las
siguientes restricciones importantes:
Slo se pueden sustituir mtodos virtuales heredados idnticos.
Un mtodo override debe coincidir con su mtodo virtual asociado.
Se puede sustituir un mtodo override.
No se puede declarar explcitamente un mtodo override como virtual.
No se puede declarar un mtodo override como static o private.
A continuacin se describe con ms detalle cada una de estas restricciones.
Herencia en C#
Recomendacin al
profesor
16
// Okay
Herencia en C#
17
Herencia en C#
18
Explicacin previa
Si se declara un mtodo
que tiene la misma
signatura que un mtodo de
una clase base, es posible
ocultar el mtodo base sin
utilizar override.
class
class Token
Token
{{ ...
...
public
public int
int LineNumber(
LineNumber( )) {{ ...
... }}
}}
class
class ComentToken:
ComentToken: Token
Token
{{ ...
...
new
new public
public int
int LineNumber(
LineNumber( )) {{ ...
... }}
}}
{ ... }
}
class ComentToken: Token
{
...
new public int LineNumber( ) { ... }
}
Herencia en C#
19
Explicacin previa
class
class Token
Token
{{ ...
...
public
public int
int LineNumber(
LineNumber( )) {{ ...
... }}
public
public virtual
virtual string
string Name(
Name( )) {{ ...
... }}
}}
class
class ComentToken:
ComentToken: Token
Token
{{ ...
...
new
new public
public int
int LineNumber(
LineNumber( )) {{ ...
... }}
public
public override
override string
string Name(
Name( )) {{ ...
... }}
}}
Herencia en C#
20
mejor que
public new virtual int LineNumber ( ) { ... }
Herencia en C#
21
Nota La palabra reservada new se puede emplear tambin para ocultar campos
y clases anidadas.
Herencia en C#
22
Explicacin previa
No siempre es conveniente
permitir que una clase sea
heredada por otra.
namespace
namespace System
System
{{
public
public sealed
sealed class
class String
String
{{
...
...
}}
}}
namespace
namespace Mine
Mine
{{
class
class FancyString:
FancyString: String
String {{ ...
... }}
}}
No es fcil crear una jerarqua de herencia flexible. La mayor parte de las clases
son autnomas y no estn diseadas para que otras clases deriven de ellas. En
trminos de sintaxis, sin embargo, el procedimiento para la derivacin de una
clase es muy sencillo y se puede escribir en muy poco tiempo. Esto hace que los
programadores puedan caer a veces en la tentacin de derivar desde una clase
que no est pensada para funcionar como clase base.
Para prevenir este problema, y para que el programador pueda comunicar mejor
sus intenciones al compilador y a otros programadores, C# permite declarar una
clase como sealed (sellada). La derivacin de una clase sellada no est
permitida.
Herencia en C#
23
Herencia en C#
24
Uso de interfaces
Objetivo del tema
Explicacin previa
En esta leccin
aprenderemos el
procedimiento para definir y
usar interfaces en C#.
Declaracin de interfaces
Herencia en C#
25
Declaracin de interfaces
Objetivo del tema
Explicacin previa
Los
Losnombres
nombresde
deinterfaces
interfaces
empiezan
empiezancon
conImayscula
Imayscula
interface
interface IToken
IToken
{{
int
int LineNumber(
LineNumber( );
);
string
string Name(
Name( );
);
}}
Sin
Sinespec.
espec.de
deacceso
acceso
Para su informacin
IToken
IToken
interface
interface
LineNumber(
LineNumber( ))
Name(
Name( ))
Mtodos
Mtodossin
sincuerpo
cuerpo
Herencia en C#
26
Herencia en C#
27
Explicacin previa
interface
interface IToken
IToken
{{
IToken
IVisitable
IVisitable
IToken
string
string Name(
Name( );
);
interface
interface
interface
interface
}}
interface
interface IVisitable
IVisitable
{{
void
void Accept(IVisitante
Accept(IVisitante v);
v);
}}
Token
class
Token
class Token:
Token: IToken,
IToken, IVisitable
IVisitable
{{ ...
concrete
...
concrete
}}
Implementacin de interfaces
Una clase puede implementar cero o ms interfaces, pero no puede extender
ms de una clase de forma explcita. La transparencia muestra un ejemplo de
este punto.
Nota Estrictamente hablando, una clase extiende siempre una clase. Si no se
especifica la clase base, una clase heredar de object implcitamente.
Herencia en C#
Recomendacin al
profesor
28
Por el contrario, una interfaz puede extender cero o ms interfaces. Por ejemplo,
el cdigo de la transparencia se podra reescribir de la siguiente manera:
En la transparencia se han
dejado intencionadamente
en blanco los mtodos de
Token. Las dos formas de
implementar una interfaz se
discutirn en las dos
transparencias siguientes.
Accesibilidad
Un aspecto importante en
este tema es que una clase
debe implementar todos los
mtodos de interfaz
heredados.
Probablemente tambin sea
conveniente mencionar que
una interfaz puede heredar
de otras interfaces. D un
ejemplo.
Una clase puede ser ms accesible que sus interfaces base. Por ejemplo, es
posible declarar una clase pblica que implemente una interfaz privada, como
se ve:
class Example
{
private interface INested { }
public class Anidada: INested { } // Okay
}
Sin embargo, una interfaz no puede ser ms accesible que sus interfaces base.
Es un error declarar una interfaz pblica que extiende una interfaz privada,
como se muestra en el siguiente ejemplo:
class Example
{
private interface INested { }
public interface IAlsoNested: INested { }
// Error al compilar
}
Mtodos de interfaz
Una clase debe implementar todos los mtodos de todas las interfaces que
extienda, independientemente de que las interfaces se hereden directa o
indirectamente.
Herencia en C#
29
Discutir la implementacin
de interfaces.
Explicacin previa
class
class Token:
Token: IToken,
IToken, IVisitable
IVisitable
{{
public
public virtual
virtual string
string Name(
Name( ))
{{ ...
...
}}
public
public void
void Accept(IVisitante
Accept(IVisitante v)
v)
{{ ...
...
}}
}}
Mismo
Mismoacceso
acceso
Mismo
Mismoretorno
retorno
Mismo
Mismonombre
nombre
Mismos
metros
par
Mismospar
parmetros
Si una clase implementa una interfaz, tiene que implementar todos los mtodos
declarados en esa interfaz. Este requisito es muy conveniente, ya que las
interfaces no pueden definir los cuerpos de sus propios mtodos.
El mtodo que la clase implementa debe ser absolutamente idntico al mtodo
de la interfaz. Tiene que ser igual en:
Acceso
Un mtodo de interfaz es pblico de forma implcita, lo que significa que el
mtodo que lo implementa debe estar declarado explcitamente como
pblico. Si se omitiera el modificador de acceso, el mtodo sera privado
por defecto.
Tipo de retorno
Si el tipo de retorno en la interfaz est declarado como T, el tipo de retorno
en la clase que la implementa no puede estar declarado como un tipo
derivado de T, sino que debe ser T. En otras palabras, C# no permite la
covarianza de tipos de retorno.
Nombre
No hay que olvidar que C# distingue maysculas y minsculas en los
nombres.
Lista de parmetros
Herencia en C#
30
El mtodo que implementa puede ser virtual, como Name en el cdigo anterior.
En ese caso, es posible sustituir el mtodo en otras clases derivadas. Por otro
lado, el mtodo que implementa tambin puede ser no virtual, como Accept en
el mismo cdigo. En este ltimo caso, no es posible sustituir el mtodo en otras
clases derivadas.
Herencia en C#
31
Explicacin previa
En esta leccin
aprenderemos a usar clases
abstractas.
Herencia en C#
32
Explicacin previa
abstract
abstract class
class Token
Token
{{
...
...
}}
class
class Test
Test
{{
static
static void
void Main(
Main( ))
{{
new
new Token(
Token( );
);
}}
}}
Token
Token
{{ abstract
abstract }}
No
Nose
sepueden
puedencrear
crearinstancias
instancias
de
deuna
unaclase
claseabstracta
abstracta
Para declarar una clase abstracta se utiliza la palabra reservada abstract, como
se muestra en la transparencia.
Las reglas que rigen el uso de una clase abstracta son prcticamente las mismas
que se aplican a una clase no abstracta. Las nicas diferencias entre usar clases
abstractas y no abstractas son:
No est permitido crear una instancia de una clase abstracta.
En este sentido, las clases abstractas son como interfaces.
Se puede crear un mtodo abstracto en una clase abstracta.
Se puede declarar un mtodo abstracto en una clase abstracta, pero no en
una que no lo sea.
Las clases abstractas comparten las siguientes caractersticas con las clases no
abstractas:
Extensibilidad limitada
Una clase abstracta puede extender como mximo otra clase o clase
abstracta. Obsrvese que una clase abstracta puede extender una clase que
no sea abstracta
Mltiples interfaces
Una clase abstracta puede implementar varias interfaces
Mtodos de interfaz heredados
Una clase abstracta debe implementar todos los mtodos de interfaz
heredados
Herencia en C#
33
Explicacin previa
Ejemplo 1
interface
interface IToken
IToken
{{
string
string Name(
Name( );
);
}}
IToken
IToken
interface
interface
abstract
abstract class
class Token:
Token: IToken
IToken
{{
string
string IToken.Name(
IToken.Name( ))
{{ ...
...
}}
...
...
}}
class
class ComentToken:
ComentToken: Token
Token
{{ ...
...
}}
class
class KeywordToken:
KeywordToken: Token
Token
{{ ...
...
}}
Token
Token
{{ abstract
abstract }}
Coment
Coment
Token
Token
concrete
concrete
Keyword
Keyword
Token
Token
concrete
concrete
Herencia en C#
34
Explicacin previa
Ejemplo 2
interface
interface IToken
IToken
{{
string
string Name(
Name( );
);
}}
abstract
abstract class
class Token
Token
{{
public
virtual
public virtual string
string Name(
Name( ))
{{ ...
...
}}
...
...
}}
IToken
IToken
interface
interface
Token
Token
{{ abstract
abstract }}
Coment
Coment
class
class ComentToken:
ComentToken: Token,
Token, IToken
IToken
{{ ...
Token
Token
...
}}
concrete
concrete
class
class KeywordToken:
KeywordToken: Token,
Token, IToken
IToken
{{ ...
...
}}
Keyword
Keyword
Token
Token
concrete
concrete
Herencia en C#
35
Explicacin previa
Parecidos
z
Diferencias
z
Tanto las clases abstractas como las interfaces existen para derivar otras clases
de ellas (o ser implementadas). Sin embargo, una clase puede extender como
mximo una clase abstracta, por lo que hay que tener ms cuidado cuando se
deriva de una clase abstracta que cuando se deriva de una interfaz. Las clases
abstractas se deben utilizar solamente para implementar relaciones del tipo es
un.
Los parecidos entre clases abstractas e interfaces son:
No se pueden crear instancias de ellas.
Esto significa que no es posible usarlas directamente para crear objetos.
No se pueden sellar.
Esto es normal, ya que no es posible implementar una interfaz sellada.
La siguiente tabla resume las diferencias entre clases abstractas e interfaces.
Interfaces
Clases abstractas
Herencia en C#
36
Explicar cmo se
implementan mtodos
abstractos.
Explicacin previa
abstract
abstract class
class Token
Token
{{
public
public virtual
virtual string
string Name(
Name( )) {{ ...
... }}
public
public abstract
abstract int
int Longitud(
Longitud( );
);
}}
class
class ComentToken:
ComentToken: Token
Token
{{
public
public override
override string
string Name(
Name( )) {{ ...
... }}
public
override
int
Longitud(
)
{
public override int Longitud( ) { ...
... }}
}}
Recomendacin al
profesor
Es obligatorio sustituir un
mtodo abstracto, pero no
es necesario sustituir un
mtodo virtual.
Herencia en C#
37
Explicacin previa
Antes de implementar un
mtodo abstracto hay que
tener en cuenta sus
caractersticas y las
restricciones que impone.
Herencia en C#
38