Interfaces genéricas de .NET
. NET define varias interfaces genéricas de uso común
de entre las que podemos elegir para implementar nuestras clases. Estas interfaces
nos permiten obtener funcionalidad adicional para nuestro objeto. Algunas
interfaces se describen en la tabla siguiente:
Interfaz
|
Descripción
|
IComparable
|
Define el ordenamiento de instancias de la clase. Es
útil si queremos utilizar la clase como un valor clave en SortedList o vamos a usar el método Sort del ArrayList.
|
IEnumerable e
IEnumerator
|
Estas
dos interfaces trabajan juntas dando soporte a los For…Each de
nuestra clase
|
IFormattable
|
Permite
definir formateos de cadena definidos por el usuario
|
IList
|
Permite
a la clase servir como fuente de datos Para controles tales como ListBox y
DataGrid. La implementación de la base es List.
|
ICloneable
|
Permite
definir exactamente como será copiado nuestro objeto.
|
IComponent
|
Provee
soporte como componente a nuestra clase en tiempo de diseño. La base de esta
implementación es Component.
|
IDataErrorInfo
|
Permite
añadir a la clase información sobre errores.
El soporte de esta interface nos permite usar el control Dataerror en
un formulario de Windows.
|
A continuación, vamos a crear una clase simple que representa
un punto. Vamos a usar esta clase como una base para la aplicación de los
interfaces IComparable,
IEnumerator IEnumerable, y de IFormattable. Estas interfaces de
usuario hacen que la clase sea más fácil de usar para otros desarrolladores.
Implementando el interface IComparable
La interfaz IComparable permite definir un orden de las instancias de clase.
Si la clase representa un objeto que lleva a una interpretación significativa
de más o menos, primero o el último, o más grande o más pequeño, es razonable
para definir la interfaz IComparable para nuestra clase.
IComparable tiene uno de los miembros, el método CompareTo. En este ejemplo, se implementa una clase que representa
un punto y compara puntos basándose en la distancia desde el origen.
Crear la clase PuntoOrdenable
1. Crear un Nuevo proyecto
Windows application y llamarlo Puntos
2. Añadir una clase
llamada CPuntoOrdenable.
3. Añadir las propiedades
X e Y a la clase CPuntoOrdenable.
Public Class CPuntoOrdenable
Private m_x As Integer = 0
Public Property X() As Integer
Get
Return (m_x)
End Get
Set(ByVal Value As Integer)
m_x = Value
End Set
End Property
Private m_y As Integer = 0
Public Property Y() As Integer
Get
Return (m_y)
End Get
Set(ByVal Value As Integer)
m_y = Value
End Set
End Property
End Class
Añadir el Interface IComparable
1. Añadir
el interface IComparable a la declaración de la clase:
Implements
IComparable
2. Hacer click
sobre IComparable con lo
que se escribirá en el código automáticamente
La
definición de CompareTo.
Public Function CompareTo(ByVal
obj As Object) As Integer Implements System.IComparable.CompareTo
End Function
El método CompareTo compara la primera instancia de la una clase, Me con otra instancia de la clase, Advertencia: Si las
dos instancias son iguales, de acuerdo con definición de la clase de la
clasificación, CompareTo devuelve 0. Si la instancia Me es más grande (la instancia comparada ocupa el
segundo lugar), CompareTo devuelve un entero positivo. Si Me es más pequeño (la instancia comparada es más grande y por tanto está
delante de Me), CompareTo devuelve un entero negativo.
Agregar código
a la función CompareTo para crear una función auxiliar, DistanciaCuadrado. Los puntos se compararon dos a la
vez, así que no
importa qué valor devuelva el método CompareTo, siempre y cuando retorne
un número positivo si Me está más lejos que el otro punto. El método DistanciaCuadrado devuelve el cuadrado de la distancia del punto desde el origen. Si se utiliza el método CompareTo la distancia real para comparar distancias, el código tendría que
trabajar con valores System.Double. Trabajar con valores System.Double
tiene tres desventajas. En primer lugar, afecta negativamente el rendimiento.
En segundo lugar, debido a la forma como se almacenan, es más trabajosa para probar
la equivalencia. En tercer lugar, el código tiene que convertir la diferencia de nuevo en
un número entero, el tipo de retorno de CompareTo.
importa qué valor devuelva el método CompareTo, siempre y cuando retorne
un número positivo si Me está más lejos que el otro punto. El método DistanciaCuadrado devuelve el cuadrado de la distancia del punto desde el origen. Si se utiliza el método CompareTo la distancia real para comparar distancias, el código tendría que
trabajar con valores System.Double. Trabajar con valores System.Double
tiene tres desventajas. En primer lugar, afecta negativamente el rendimiento.
En segundo lugar, debido a la forma como se almacenan, es más trabajosa para probar
la equivalencia. En tercer lugar, el código tiene que convertir la diferencia de nuevo en
un número entero, el tipo de retorno de CompareTo.
Public Function CompareTo(ByVal
obj As Object) As Integer Implements System.IComparable.CompareTo
Return (Me.DistanciaCuadrado() - CType(obj,CPuntoOrdenable).DistanciaCuadrado())
End Function
Private Function DistanciaCuadrado() As
Integer
Return (m_x *
m_x) + (m_y * m_y)
End Function
'Constructor
Public Sub New(ByVal x As Integer, ByVal y As Integer)
m_x = x
m_y = y
End Sub
Testear el interfaz
Una forma sencilla de probar la interfaz IComparable sería la creación de una lista de
puntos, ordenarlos, y luego imprimir los puntos ordenados para comprobar que están en orden.
En lugar de eso, este procedimiento genera un grupo de puntos colocados al azar. Pintaremos los puntos del formulario con diferente densidad de color y quedarán clasificados según varía dicha densidad de color.
puntos, ordenarlos, y luego imprimir los puntos ordenados para comprobar que están en orden.
En lugar de eso, este procedimiento genera un grupo de puntos colocados al azar. Pintaremos los puntos del formulario con diferente densidad de color y quedarán clasificados según varía dicha densidad de color.
1. Abrir el Form1 y
arrastrar sobre él un botón. Poner sobre la propiedad Texto la palabra Dibujar.
2.Agregar este código al evento click del botón para
generar puntos, ordenarlos, y mostrarlos
en el formulario. El método de ArrayList Ordenar
utiliza el método Comparable.CompareTo
para
clasificar las instancias de CPuntoOrdenable. La
intensidad del color depende de la posición del punto entre el resto de puntos
ordenados. Cuanto más alto
el valor, menos intenso será el color.
el valor, menos intenso será el color.
Private Sub Button1_Click(ByVal
sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim puntos As New ArrayList()
Dim rgen As New System.Random()
Dim pt As
CPuntoOrdenable
Dim count As Integer
Dim pintar As
Graphics = Me.CreateGraphics
Dim aColor As Color
For count = 0 To 249
puntos.Add(New CPuntoOrdenable(rgen.Next(200),rgen.Next(200)))
Next
puntos.Sort()
For count = 0 To 249
pt = CType(puntos(count), CPuntoOrdenable)
aColor =
System.Drawing.Color.FromArgb(25, 25, count)
Dim brush As New System.Drawing.SolidBrush(aColor)
pintar.FillEllipse(brush,
pt.X, pt.Y, 10, 10)
brush.Dispose()
Next
End Sub
3. Presionar F5 para ejecutar el programa. Cada vez
que se haga clic en el botón Dibujar, se añadirán al formulario 250 puntos más.
Debido a que los puntos no están dibujados en
el evento Paint, los puntos no se quedarán en el formulario si se minimiza y luego se maximiza.
el evento Paint, los puntos no se quedarán en el formulario si se minimiza y luego se maximiza.
Para obtener una clara indicación de que los puntos
están siendo
ordenados, comentar la llamada a ordenar y, a continuación, ejecutar el programa.
ordenados, comentar la llamada a ordenar y, a continuación, ejecutar el programa.
Implementando los interfaces IEnumerable y IEnumerator
En el
ejemplo anterior,
se han generado puntos, añadiéndolos a un
objeto ArrayList,
y ordenándolos y luego dibujándolos en el formulario. En el siguiente ejemplo, se crea una clase, CListaPuntoOrdenado, que contiene un grupo de puntos. En lugar de utilizar un bucle para acceder a los miembros de la clase ArrayList y luego modificar cada elemento con el tipo CPuntoOrdenado, seremos capaces de utilizar un bloque For Each, que devuelve sólo un objeto CPuntoOrdenado.
y ordenándolos y luego dibujándolos en el formulario. En el siguiente ejemplo, se crea una clase, CListaPuntoOrdenado, que contiene un grupo de puntos. En lugar de utilizar un bucle para acceder a los miembros de la clase ArrayList y luego modificar cada elemento con el tipo CPuntoOrdenado, seremos capaces de utilizar un bloque For Each, que devuelve sólo un objeto CPuntoOrdenado.
La interfaz IEnumerable tiene uno de los miembros, el método GetEnumerator. El
Método GetEnumerator devuelve una instancia de una clase que implementa la interfaz IEnumerator. La interfaz IEnumerator tiene tres miembros, y restablece el método MoveNext y la propiedad actual. Los tres miembros trabajan juntos para enumerar los
miembros de la clase CListaPuntoOrdenado como se puede ver aquí.
Dim enumerator
As IEnumerator = puntos.GetEnumerator()
While enumerator.MoveNext
pt = CType(enumerator.Current, CPuntoOrdenable)
End While
Crear la clase CListaPuntoOrdenado
1. Añadir una nueva clase
al proyecto, llamada CListaPuntoOrdenado.
2. Modificar la clase
añadiendo el interfaz IEnumerable:
Public Class CListaPuntoOrdenado
Implements IEnumerable
End Class
3. Añadimos el constructor
Public Sub New()
End Sub
usando System.Collections;
4. Añadir una instancia de
ArrayList y un método
llamado AgregarPuntosAleatorios el cual
añade un número de puntos generados aleatoriamente a una clase ArrayList. Este
código es similar al de la sección anterior.
Private m_puntos As New ArrayList()
Public Sub AddRandomPoints(ByVal
howMany As Integer,
ByVal maximum As
Integer)
m_puntos.Clear()
Dim rgen As New
System.Random()
Dim count As Integer
For count = 0 To
howMany - 1 m_puntos.Add(New
CPuntoOrdenable(rgen.Next(maximum), rgen.Next(maximum)))
Next
m_puntos.Sort()
End Sub
Anadir la clase interna IEnumerator
1. Declarar una nueva
clase dentro de la clase de CListaPuntoOrdenado y llamarla EnumeradorPuntos para que
implemente el interfaz del IEnumerator.
Private Class CEnumeradorPuntos
Implements IEnumerator
Public ReadOnly Property Current() As
Object Implements
System.Collections.IEnumerator.Current
Get
End Get
End Property
Public Function MoveNext() As Boolean Implements System.Collections.IEnumerator.MoveNext
End Function
Public Sub Reset() Implements System.Collections.IEnumerator.Reset
End Sub
End Class
La clase CEnumeradorPuntos se llama clase
interna, ya que está definida dentro de otra clase. Una instancia de esta
clase se crea y se devuelve por el método GetEnumerator. El usuario de la instancia CEnumeradorPuntos necesita conocer sólo la clase que implementa
la interfaz IEnumerator. Así la única clase que necesita
saber acerca de la clase CEnumeradorPuntos es la clase CListaPuntoOrdenado.
2.Hacer click
en IEnumerator y se despliegan los métodos del interface
a implementar
Private Class CEnumeradorPuntos
Implements IEnumerator
Public ReadOnly Property Current() As
Object Implements
System.Collections.IEnumerator.Current
Get
End Get
End Property
Public Function MoveNext() As
Boolean Implements
System.Collections.IEnumerator.MoveNext
Implements System.Collections.IEnumerator.MoveNext End Function
Public Sub Reset() Implements
System.Collections.IEnumerator.Reset
End Sub
End Class
3. Añadir estos campos a la clase CEnumeradorPuntos clase. El primero se refiere
a la colección m_puntos de la instancia CListaPuntoOrdenado. m_posicion es la posición actual en la enumeración. m_CuentaInicial es el recuento de puntos en m_puntos cuando el enumerador es instanciado. Por convención en .NET Framework, el
MoveNext y el Current del Enumerador deben fallar si la colección enumerada cambia durante la enumeración. En este ejemplo, vamos a usar la cuenta inicial de puntos para comprobar si la clase ArrayList ha cambiado.
a la colección m_puntos de la instancia CListaPuntoOrdenado. m_posicion es la posición actual en la enumeración. m_CuentaInicial es el recuento de puntos en m_puntos cuando el enumerador es instanciado. Por convención en .NET Framework, el
MoveNext y el Current del Enumerador deben fallar si la colección enumerada cambia durante la enumeración. En este ejemplo, vamos a usar la cuenta inicial de puntos para comprobar si la clase ArrayList ha cambiado.
Dim m_puntos As ArrayList
Dim m_posicion
As Integer = -1
Dim
m_cuentainicial As Integer
4. Añadir esto al constructor.
Public Sub New(ByVal puntos As
ArrayList
m_puntos =
puntos
m_cuentainicial = puntos.Count
End Sub
5. Añadir este código para el método Reset. Se implementa
mediante el enumerador
mediante la adición de 1 a m_posicion con cada llamada a MoveNext. La propiedad Current devuelve el elemento en los m_puntos de ArrayList al índice m_posicion.
mediante la adición de 1 a m_posicion con cada llamada a MoveNext. La propiedad Current devuelve el elemento en los m_puntos de ArrayList al índice m_posicion.
Debido a que el primer valor de la enumeración se
encuentra llamando al método MoveNext, el método Reset necesita mantener el valor del
índice a la derecha antes del primer elemento de la clase ArrayList. El primer elemento en ArrayList en el índice es 0,
por lo que el método Reset
establece m_posicion a -1.
Public Sub Reset() Implements
System.Collections.IEnumerator.Reset
m_posicion
= -1
End Sub
6. Agregar el siguiente código para el método MoveNext. La primera prueba determina si las instancias de CPuntoOrdenable se han añadido o eliminado a m_puntos en el ArrayList. Si no, m_posicion se incrementa. En caso contrario, el código produce una excepción, InvalidOperationException.
Public Function MoveNext() As
Boolean Implements
System.Collections.IEnumerator.MoveNext
If (m_cuentainicial = m_puntos.Count) Then
m_posicion += 1
If (m_posicion >= m_puntos.Count) Then
Return (False)
Else
Return (True)
End If
Else
Throw New
InvalidOperationException("La Coleccion ha
cambiado durante la enumeration.")
End If
End Function
7. Añadir este código a la
propiedad Current.
Public ReadOnly Property
Current() As Object
Implements
System.Collections.IEnumerator.Current
Get
If
(m_cuentainicial <> m_puntos.Count) Then
Throw New
InvalidOperationException("La Colección ha
cambiado durante la enumeration.")
ElseIf
(m_posicion >= m_puntos.Count) Then
Throw New
InvalidOperationException("El valor de la Enumeration es invalido.")
Else
Return
(m_puntos(m_posicion))
End If
End Get
End Property
Ahora que hemos definido
el enumerador para la clase, podemos implementar el método GetEnumerador en la
clase CListaPuntoOrdenado.
Añadir el interfaz IEnumerable
1. Hacer click
en la interfaz IEnumerable en el nombre de método GetEnumerator. Y
añadir esta declaración para el método.
Public Function GetEnumerator() As
System.Collections.IEnumerator Implements
System.Collections.IEnumerable.GetEnumerator
Return
(New CEnumeradorPuntos(m_puntos))
End Function
Testear los interfaces
1. Modificar el código del
botón del formulario para usar una estructura For Each.
Private Sub Button1_Click(ByVal
sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim puntos As New
CListaPuntoOrdenado()
puntos.AddRandomPoints(250, 200)
Dim graficos As Graphics = Me.CreateGraphics
Dim contador As Integer = 1
Dim aColor As Color
Dim pt As CPuntoOrdenable
For Each pt In puntos
aColor = System.Drawing.Color.FromArgb(25,
25, contador)
contador
+= 1
Dim brocha As New System.Drawing.SolidBrush(aColor)
graficos.FillEllipse(brocha, pt.X,
pt.Y, 10, 10)
brocha.Dispose()
Next
Dim enumerator As IEnumerator =
puntos.GetEnumerator()
While enumerator.MoveNext
pt = CType(enumerator.Current,
CPuntoOrdenable)
End While
End Sub
2. Presionar F5 para ejecutar el programa, el resultado es
similar al ejemplo inicial.
Implementando el interface IFormattable
Un
posible formateo de cadena para mostrar un valor System.Decimal como valor de la moneda
puede ser el siguiente:
MessageBox.Show (String.Format ("{0: C}", cuenta.saldo))
El tipo de datos System.Decimal ha definido la cadena de formato C para que devuelva una cadena representando la moneda. También se pueden definir los esquemas de formato personalizados para las clases que nosotros creemos. En la tarea siguiente, vamos a añadir dos opciones de formato personalizado a la clase CPuntoOrdenado. Primero, se imprime una opción tipo long indicada por L, imprime el punto como (x, y). En segundo lugar, una opción tipo Short indicada por S, imprime el punto como x: y. Vamos a definir tres sobrecargas del método ToString para proporcionar un comportamiento de un formato coherente para la clase CPuntoOrdenado. Las tres sobrecargas se describen en la siguiente tabla.
Sobrecarga
|
Comportamiento
|
ToString()
|
Dim p As New CPuntoOrdenado(1,2)
Dim s As String = p.ToString()
|
|
Valor de s: (1,2)
|
ToString(format As String)
|
Dim p As New CPuntoOrdenado (1,2)
Dim plong As String = p.ToString("L")
Dim pshort As String = p.ToString("S")
|
|
Valor de plong:
(1,2)
|
|
Valor de pshort: 1;2
|
ToString(format As String, _
formatprovider As _
IFormatProvider)
|
Dim
p As New CPuntoOrdenado (1,2)
Dim
s As String =_
String.Format("{0:L}", p))
|
|
Valor de s; (1,2)
|
La primera sobrecarga reemplaza el método ToString que se encuentra en la clase System.Object. System.Object es la clase base para todos los tipos
de Visual Basic. La segunda sobrecarga es un método ToString definido sólo para la clase. No es ni una sobrecarga de una implementación de una clase base ni la implementación de un método del interfaz. La última sobrecarga es la implementación del método IFormattable.ToString, el único miembro de la Interfaz IFormattable. Esta es la versión de ToString que se llama si es evaluado el formato de la
expresión.
También se puede implementar una clase IFormatProvider para proporcionar opciones de
formato adicionales para los tipos base. En este ejemplo, si este código no reconoce
el formato string, Con lo que hay que pasar a lo largo de la interfaz IFormatProvider a otra llamada con el método ToString.
Agregar el interfaz IFormattable
1. Añadir el interfaz IFormattable a la clase CPuntoOrdenable:
Public Class CPuntoOrdenable
Implements IComparable, IFormattable
End Class
2. Añadir este código al
método IFormattable.ToString.
Debido a que la clase System.Object
implementa menos parámetros en el método ToString, este método ToString es una sobrecarga. Si la clase CPuntoOrdenable
no reconoce el
formato string, los métodos individuales crean una
cadena al pasar el formatProvider a los métodos
ToString de los campos individuales.
Public Function ToString1(ByVal
formato As String,
ByVal ProveedorFormato As
System.IFormatProvider) As String Implements
System.IFormattable.ToString
Dim resultado As String
Select Case formato.ToUpper()
Case ("L")
resultado = String.Format("({0}, {1})", m_x, m_y)
Case ("S")
resultado =
String.Format("{0},{1}",
m_x, m_y)
Case Else
resultado =
(m_x.ToString(formato, ProveedorFormato) & "
" &
m_y.ToString(formato, ProveedorFormato))
End Select
Return
(resultado)
End Function
Sobrecargar el método ToString
Añadir dos sobrecargas de ToString más para que la clase
CPuntoOrdenable pueda
formatear de manera coherente en todos los métodos ToString. Cada sobrecarga de llama al método ToString de la interfaz IFormattable. El método predeterminado ToString de la clase CPuntoOrdenable devuelve la versión larga.
formatear de manera coherente en todos los métodos ToString. Cada sobrecarga de llama al método ToString de la interfaz IFormattable. El método predeterminado ToString de la clase CPuntoOrdenable devuelve la versión larga.
Public Function ToString1(ByVal
format As String)
As String
Return Me.ToString1(format, Nothing)
End Function
Public Overrides Function
ToString() As String
Return Me.ToString1("L")
End Function
Testear el interface IFormattable
1. Reemplazar
el código en el controlador de eventos Click en el botón Dibujar con
este código, esto crea algunos puntos y luego los arrastra la etiqueta con sus coordenadas:
este código, esto crea algunos puntos y luego los arrastra la etiqueta con sus coordenadas:
Private Sub Button1_Click(ByVal
sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim puntos As New
CListaPuntoOrdenado()
puntos.AddRandomPoints(5, 200)
Dim grafico As Graphics = Me.CreateGraphics
Dim pt As CPuntoOrdenable
For Each pt In puntos
grafico.FillEllipse(System.Drawing.Brushes.Black, pt.X, pt.Y, 10, 10)
Dim
ptlocalizacion As String
= String.Format("{0:L}",
pt)
grafico.DrawString(ptlocalizacion,
New Font("Arial",
8), System.Drawing.Brushes.Black, pt.X
+ 11, pt.Y)
Next
End Sub
2. Presionar F5 para
ejecutar el programa y ver los resultados
Otros dos usos de los interfaces
En la programación con. NET Framework, se implementan
interfaces principalmente para
prestación de servicios de nuestra clase. Es posible, además, utilizar una interfaz para un proyecto en las dos situaciones siguientes:
Herencia Múltiple clases que sólo pueden tener una clase base, pero se pueden implementar varias interfaces. Debido a que las interfaces se comportan polimórficamente, como las clases base, se pueden utilizar las interfaces para simular herencia múltiple. Supongamos que se crea una clase de CPatio y de ella que se derivan tanto CCesped y CJardin, pero no comparten una clase base común de System.Object. Podemos optar por implementar una interfaz ICesped y luego implementar la interfaz ICesped en una clase CCesped. A continuación, crear CJardin como una clase base. Cuando se crea la clase de CPatio esta hereda de CJardin e implementa ICesped como se puede ver aquí:
prestación de servicios de nuestra clase. Es posible, además, utilizar una interfaz para un proyecto en las dos situaciones siguientes:
Herencia Múltiple clases que sólo pueden tener una clase base, pero se pueden implementar varias interfaces. Debido a que las interfaces se comportan polimórficamente, como las clases base, se pueden utilizar las interfaces para simular herencia múltiple. Supongamos que se crea una clase de CPatio y de ella que se derivan tanto CCesped y CJardin, pero no comparten una clase base común de System.Object. Podemos optar por implementar una interfaz ICesped y luego implementar la interfaz ICesped en una clase CCesped. A continuación, crear CJardin como una clase base. Cuando se crea la clase de CPatio esta hereda de CJardin e implementa ICesped como se puede ver aquí:
Public Class CPatio
Inherits CJardin
Implements ICesped
End Class
Al parecer, no se ha ganado mucho con este código ya
que hay que reimplementar todos los miembros de ICesped. Afortunadamente, podemos
servirnos de la contención y de la delegación
para reutilizar parte de nuestro trabajo. En la clase CPatio, se puede crear una instancia
privada de la clase ICesped. Esta es la contención.
A continuación, implementaremos los métodos de ICesped mediante una llamada
al método correspondiente de la instancia privada Cesped. Esto se llama delegación. Estamos delegando el trabajo de la interfaz de ICesped en el miembro contenido en la figura del miembro
Cesped.
Supongamos que la clase ICesped tiene un método Crecer() y una propiedad Altura. Su código de podría ser algo
como esto:
Public Class CPatio
Inherits CJardin
Implements ICesped
Private m_cesped As New Cesped()
Public Sub Crecer() Implements ICesped.Crecer
m_cesped.Crecer()
End Sub
Public Property
Altura() As Integer
Implements ICesped.Altura
Get
Return m_cesped.Altura
End Get
Set(ByVal Value As Integer)
m_cesped.Altura = Value
End Set
End Property
End Class
Anteriormente
hemos creado un array de clases SourceFile para utilizar como fuente de datos
en un control DataGrid. En general, se desea que el modelo de datos se adapte a
los datos y, a continuación, se desea proporcionar métodos para apoyar a la
interfaz de usuario. También podemos limitar la cantidad de control que la
interfaz de usuario tiene sobre el modelo. Por ejemplo, puede que no se desee permitir actualizaciones. Se pueden evitar
las actualizaciones al implementar una
interfaz en su clase. Cuando se crea una referencia al modelo de datos para la interfaz de usuario, se proporciona
sólo una referencia a la interfaz. Por
supuesto, se podría proporcionar una referencia al modelo completo, pero el uso
de una interfaz puede dejar al compilador algunos de los trabajos,
alertando cuando se están tratando de
actualizar los datos.
No hay comentarios:
Publicar un comentario