2. Agenda
Ahora conocemos como crear juegos en C#,
jugables (y vendibles).
Sin embargo, existen algunas características de
C# que es necesario conocerlas.
Esto hace posible nuevas cosas
Previamente sabemos lo suficiente de
programación para lograr la implementación de un
algoritmo.
Sin embargo, estas técnicas, nos hacen
organizar y reusar código.
3. Problemas al desarrollar
Cuando nos proponemos crear un gran
programa, existen un número de problemas que
se deben resolver.
Asegurase que el programa nunca se aborte.
Separar el sistema en pedazos discretos que se
puedan desarrollar de manera separada.
Realizar esto de manera rápida y de adicionar
nuevos comportamientos.
Este tipo de problemas es lo que el diseño
orientado a objetos resuelve.
4. Recordando los Objetos
Un objeto es una colección de datos (campos) y
comportamientos (métodos) que son creados
para un propósito particular.
Un juego en XNA es un objeto
Contiene campos de datos del mundo del juego y
diversos métodos incluyendo Draw y Update.
Además, se ha creado nuestros propios objetos.
GameSpriteStruct es un objeto que contiene
campos que describen un sprite en la pantalla
5. Objetos y cohesión
La cohesión en ingeniería del software es una
medida de cómo de juntos están los objetos.
Debe contener solo elementos que son
directamente relacionados a tareas que fueron para
las que fueron creadas.
No debe ser afectado por elementos externos.
Debe usar el mínimo de interacciones externas.
La cohesión de un objeto es, la facilidad de
cambiar su contenido sin afectar otros objetos.
La cohesión también es, la facilidad de
reemplazarlo con otro objeto que haga el mismo
trabajo.
6. Cohesión del GameSpriteStruct
El GameSpriteStruct que se ha creado no tiene
una alta cohesión.
Los datos de los campos en la estructura son todos
públicos, por lo que el código de otras clases lo
pueden usar directamente.
Los métodos Update y Draw son ejecutados por
código fuera del objeto.
Si queremos modificar la manera en que los
sprites trabajan, debemos cambiar diferentes
partes del programa.
El código foráneo del sprite puede corromper su
contenido
7. Crear un BatSpriteStruct
Podemos cosiderar como crear un objeto que
representa el “bat” en el juego.
Hasta ahora ha sido una instancia de
GameSpriteStruct llamada bread.
Ahora se creará una nueva estructura que solo
se encargará del “bat” en cualquier tipo de juego.
Contendrá ambos campos para posicionar el
“bat” y ademas todos los comportamientos
update y draw que son necesarios.
8. Proteger los datos en el objeto
Vamos a crear todos los campos del tipo privado.
Por lo que no podrán ser modificados desde
fuera del objeto
struct BatSpriteStruct
{
private Texture2D spriteTexture;
private Rectangle spriteRectangle;
private float x;
private float y;
private float xSpeed;
private float ySpeed;
// rest of BatSpriteStruct goes here
}
9. Convención para nombrar
privados
Esta es la convención en C# que identifica los
ítems privados, inician con una letra minúscula.
Esto hace mas fácil de comprender el programa.
struct BatSpriteStruct
{
private Texture2D spriteTexture;
private Rectangle spriteRectangle;
private float x;
private float y;
private float xSpeed;
private float ySpeed;
...
}
10. Comportamiento del BatSpriteStruct
Para comenzar, debemos enfocarnos en 4 cosas
que sabemos que el “bat” debe hacer.
Cargar su contenido.
Iniciar un nuevo juego.
Auto actualizarse.
Auto dibujarse.
En este momento estas acciones son ejecutas
por métodos fuera del objeto BatSpriteStruct.
Ahora los traeremos dentro del objeto.
11. El método update en BatSpriteStrcut
Este código provee el comportamiento update
para el “bat”.
Note que lee el gamepad por si solo.
public void Update()
{
GamePadState gamePad1 =
GamePad.GetState(PlayerIndex.One);
x = x + (xSpeed * gamePad1.ThumbSticks.Left.X);
y = y - (ySpeed * gamePad1.ThumbSticks.Left.Y);
spriteRectangle.X = (int)x;
spriteRectangle.Y = (int)y;
}
12. Objetos y encapsulación
La encapsulación es otro termino que se utiliza
en el desarrollo de software.
Un objeto encapsula datos y comportamientos
que son usados por métodos y otros objetos.
Lo demás objetos no necesitan saber como
trabaja el objeto actual, ellos deben saber como
requerir el comportamiento requerido.
Esta es una buena vía para ocultar la
complejidad.
14. Acoplamiento entre los objetos
Cuando el juego esta en ejecución, la “bola”
necesita conocer donde esta el “bat”.
Esto es para que la bola sepa cuando rebotar
con el bat.
El bat necesita proveer una manera para que el
balon pueda averiguar donde esta.
El bat y la bola están acopladas, es decir que una
esta usando los servicios proveídos por el otro.
Si cambiamos como el bat trabaja, debemos
cambiar tambien el de la bola.
15. Mucho acoplamiento es malo
Si varios objetos son acoplados juntos, el
programa puede volverse dificil de manejar.
Si un objeto es cambiado, este puede afectar a
los demas.
Esto es particularmente importante, cuando se
considera que los objetos pueden necesitar
cambiarse para fijar sus fallos.
El diseño del sistema debe reducir la cantidad de
acoplamiento entre los objetos contenidos en el.
16. El método CheckCollision
Este objeto puede ser adicionado al objeto
BatSpriteStruct.
Este código permite a otros objetos saber si se
ha colisionado con el bat.
Este devuelve el resultado de una prueba de
intersección con el valor del rectángulo que es
suplido como parámetro.
public bool CheckCollision(Rectangle target)
{
return spriteRectangle.Intersects(target);
}
17. Conectar los objetos del juego
El sprite balón (que administra el balón en el
juego) debe habilitar la llamada del método
CheckCollision en el bat.
Para hacer esto el balón necesitará tener una
referencia a la instancia de BatSpriteStruct que
es implementada por el bat en el juego.
La mejor manera de hacer esto es dar al sprite
ball una referencia para el juego.
Luego se puede usar cualquier por cualquier
miembro del juego.
18. El método update BallSprite
Este es el código del método update para el
método BallSpriteStruct.
Esto da una referencia a el juego
public void Update (BreadAndCheeseGame game)
{
// Check to see if the ball has hit the bat
if (game.BreadBat.CheckCollision(spriteRectangle))
{
// bat has hit the ball.
ySpeed = ySpeed * -1;
}
// Other updates here
}
19. El parámetro Game para el método
update
El método update tiene un solo parámetro, el cual
da una referencia al juego que contiene esta
bola.
public void Update (BreadAndCheeseGame game)
{
// Check to see if the ball has hit the bat
if (game.BreadBat.CheckCollision(spriteRectangle))
{
// bat has hit the ball.
ySpeed = ySpeed * -1;
}
// Other updates here
}
20. Usar el parámetro
El método update puede ahora usar el campo
BreadBat del juego para verificar las colisiones.
Esta es la manera en que los dos sprites están
acoplados.
public void Update (BreadAndCheeseGame game)
{
// Check to see if the ball has hit the bat
if (game.BreadBat.CheckCollision(spriteRectangle))
{
// bat has hit the ball.
ySpeed = ySpeed * -1;
}
// Other updates here
}
21. El método update de BallSpriteStruct
Este método update será llamado cuando el
juego esta corriendo.
Será llamado por el método update en
BreadAndCheeseGame.
Moverá la bola y hará que rebote
Verificará las colisiones entre el bat y el la bola.
Es dada una referencia al juego de donde es
parte.
22. El método update del
BreadAndCheeseGame
En estos momentos el juego solo actualiza los
sprites bread y cheese (luego se adicionaran mas
detalles).
Se llama al método update para cada uno los
sprites.
protected override void Update(GameTime gameTime)
{
// Update method for BreadAndCheeseGame
BreadBat.Update(this);
CheeseBall.Update(this);
base.Update(gameTime);
}
23. El significado de This
En ambos métodos las llamadas tienen como
parámetros la palabra This.
En C# esta palabra indica “una referencia
(apuntador) al mismo objeto en el cual se usa”
protected override void Update(GameTime gameTime)
{
// Update method for BreadAndCheeseGame
BreadBat.Update(this);
CheeseBall.Update(this);
base.Update(gameTime);
}
24. Las interacciones para
BatSpriteStruct
Método Descripción Usuarios
LoadTexture Carga la textura dentro
del bat
BreadAndCheeseGam
e
StartGame Calcula el tamaño del bat
y su posición de incicio
BreadAndCheeseGam
e
Draw Dibuja el bat BreadAndCheeseGam
e
Update Actualiza el bat BreadAndCheeseGam
e
CheckCollision Verifica la colisión con el
bat
Ball
Estos son los métodos en BatSpriteStruct
que permiten a otros objetos interactuar con
el.
Es mejor si estas interacciones son
designadas dentro de un sistema al inicio
25. Objetos y mensajes
Cuando el balón golpea la parte baja de la
pantalla, esto causa la perdida de una vida.
El balón necesitará decirle al juego que esto esta
pasando.
Si esta es la última vida, el juego deberá de
finalizar.
Este tipo de mensaje es enviado por la llamada
del método:
El método BallSpriteStrcut hrá una llamada al
método LoseLife en BreadAndCheeseGame.
26. Mensajes en BreadAndCheeseGame
Método Descripción Usuarios
LoseLife Una vida ha sido
perdida
Ball
AddToScore El jugador ha
golpeado algo
Ball
BallSpriteStruct necesita decirle al juego
cuando una vida se perdió.
Ya que BallSpriteStruct no es el objeto
administrador del puntaje, necesita decirle al
juego cuando un jugador ha puntuado.
27. Interacciones vrs. Mensajes
Los objetos pueden interactuar con otros objetos
(update), y además pueden enviarles mensajes
(LoseLife).
Aunque los dos son implementados por medio de
métodos, hay que tener cuidado acerca de su
diferencia.
Un mensaje es algo que puede causar que un
objeto cambie su estado.
Mas que preguntar al objeto para hacer algo, el
puede cambiar el estado actual del objeto
28. Mensajes y organización
Esto significa que cuando diseñamos una
solución que contiene diferentes objetos, es
necesario administrar como los objetos deben
interactuar y como estos afectan el estado del
sistema.
Algunas de las transiciones en el diagrama de
estados serán cambiados por mensajes enviados
por llamada a métodos dentro de los objetos del
juego.
Hay que ser muy cuidadoso en como se
organiza, para que luego sea fácil crear el
código.
29. Objetos contenedores
Algunos objetos pueden contener a otros.
El arreglo es un ejemplo de esto.
En el caso del juego, podemos crear un
estructura llamada TargetRowStruct que
almacena un número de ítems objetivos.
Estos serán tratados como ítems singulares
desde el punto de vista del juego en si.
Esto hace la administración mucho más fácil.
30. Fondo y Pantallas de titulos
Los dos objetos finales que son requeridos uno
como imagen de fondo del juego y otro para
mostrar en titulo del juego,
El método update del título del juego, debe
verficar si se ha presionado el botón A y luego
enviar un mensaje para iniciar el juego.
El juego debe proveer un método StartGame que
puede ser llamado para recibir este mensaje e
iniciar la ejecución del juego
32. Resumen
Crear soluciones usando objetos facilita mucho
administrar el programa.
Un objeto con alta cohesión es autónomo,
Si un método en un objeto usa un método en
otro, se dice que los dos están acoplados.
Los objetos interactúan por medio de llamadas
entre ellos.
Un mensaje es una interacción que puede causar
que un objeto cambie de estado.
La encapsulación colocar los comportamientos
dentro de los objetos.
33. Verdadero o Falso
Un objeto con alta cohesión puede hacer muchas
cosas.
El acoplamiento resulta con código en un objeto
para utilizar métodos en otros.
Los métodos encapsulados deben tener
identificadores que inicien con “enc”.
Un mensaje a un objeto es llevado a otro por la
llamada a un método de otro.
Para la implementación de la encapsulación,
todos los métodos deben ser privados
34. Verdadero o Falso
Un objeto con alta cohesión puede hacer muchas
cosas.
El acoplamiento resulta con código en un objeto
para utilizar métodos en otros.
Los métodos encapsulados deben tener
identificadores que inicien con “enc”.
Un mensaje a un objeto es llevado a otro por la
llamada a un método de otro.
Para la implementación de la encapsulación,
todos los métodos deben ser privados
35. Verdadero o Falso
Un objeto con alta cohesión puede hacer muchas
cosas.
El acoplamiento resulta con código en un objeto
para utilizar métodos en otros.
Los métodos encapsulados deben tener
identificadores que inicien con “enc”.
Un mensaje a un objeto es llevado a otro por la
llamada a un método de otro.
Para la implementación de la encapsulación,
todos los métodos deben ser privados
36. Verdadero o Falso
Un objeto con alta cohesión puede hacer muchas
cosas.
El acoplamiento resulta con código en un objeto
para utilizar métodos en otros.
Los métodos encapsulados deben tener
identificadores que inicien con “enc”.
Un mensaje a un objeto es llevado a otro por la
llamada a un método de otro.
Para la implementación de la encapsulación,
todos los métodos deben ser privados
37. Verdadero o Falso
Un objeto con alta cohesión puede hacer muchas
cosas.
El acoplamiento resulta con código en un objeto
para utilizar métodos en otros.
Los métodos encapsulados deben tener
identificadores que inicien con “enc”.
Un mensaje a un objeto es llevado por la llamada
a un método en ese objeto.
Para la implementación de la encapsulación,
todos los métodos deben ser privados
38. Verdadero o Falso
Un objeto con alta cohesión puede hacer muchas
cosas.
El acoplamiento resulta con código en un objeto
para utilizar métodos en otros.
Los métodos encapsulados deben tener
identificadores que inicien con “enc”.
Un mensaje a un objeto es llevado por la llamada
a un método en ese objeto.
Para la implementación de la encapsulación,
todos los métodos deben ser privados
40. Agenda
Estamos iniciando a usar objetos para organizar
el software.
Si administramos la manera en que los objetos
interactúan y que es lo que expone a otros
objetos, podemos diseñar soluciones que son
fáciles de construir , probar y mantener.
Hasta el momento, se han utilizado estructuras
como la base del diseño de objetos.
En esta sesión, mostraremos la diferencia entre
las estructuras en C# y las clases y como las
clases ayudan a crear soluciones mucho más
fáciles.
41. Actualizar la estructura
Usamos estructuras para juntar datos y
comportamientos (métodos) y los campos de
datos (variables) para que los programas sean
fácil de administrar.
public struct BackgroundSpriteStruct
{
private Texture2D spriteTexture;
private Rectangle spriteRectangle;
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(spriteTexture, spriteRectangle,
Color.White);
}
// Other sprite methods here
}
42. Crear la variable de control del
“fondo”
El programa BreadAndCheese contiene una
variable llamada Background que contiene el
fondo a usar en el programa.
Los métodos en la clase puede usar estas
variables para dibujar el fondo que es requerido.
// Game World
public BackgroundSpriteStruct Background;
...
Background.Draw(spriteBatch);
43. Crear la clase del fondo
Esto es exactamente el m ismo código, con
excepción que el tipo ahora a sido creado como
una clase.
Esto afecta la manera en que el tipo es creado y
usado
public class BackgroundSpriteClass
{
private Texture2D spriteTexture;
private Rectangle spriteRectangle;
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(spriteTexture, spriteRectangle,
Color.White);
}
// Other sprite methods here
}
44. Crear la variable Background
Las clases son administradas por referencia.
Las estructuras son administradas por valor.
Cuando declaramos una variable
BackgroudSpriteStruct tenemos un lugar donde
podemos almacenar un fondo.
Cuando declaramos una variable
BackgroundSpriteClass, tenemos una referencia
que puede referirse a instancias de
BackgroundSpriteClass en la memoria.
En otras palabras, la declaración crea una
etiqueta.
// Game World
public BackgroundSpriteClas Background;
45. Clases y referencia
Ya previamente se ha discutido las referecnias.
Muchos tipos XNA son administrados por referencia
Se puede considerar una referencia como una
etiqueta.
// Game World
public BackgroundSpriteClass Background;
46. Crear una instancia
Cuando creamos una instancia y asignamos una
referencia, es tratar de etiquetar con una cuerda.
Podemos seguir las cuerdas para llegar a la
instancia.
Background = new BackgroundSpriteClass();
47. Referencias y clases
Cualquier tipo que es creado como una clase
puede ser administrado por referencia.
Si intentamos seguir una referencia, antes de
hacer la referencia a algo el programa retorna un
error cuando se ejecuta.
// Game World
public BackgroundSpriteClas Background;
...
Backgound.Draw(spriteBatch);
48. Múltiples referencias a una instancia
Cuando una referencia es asignada a otra, las
dos hacen referencia a la misma instancia.
BackgroundSpriteClass Background =
new BackgroundSpriteClass ();
BackgroundSpriteClass temp = Background;
49. Objetos no usados en memoria
Es posible crear objetos en la memoria, los
cuales no tienen una referencia.
Estos serán removidos por el colector de basura.
BackgroundSpriteClass Background =
new BackgroundSpriteClass ();
Background = new BackgroundSpriteClass ();
50. Por que ambos con referencias
Hasta ahora no se observa como las referencias
adicionan valor a los procesos de programación.
Adicionan un capa de complicaciones y
potenciales errores.
Que es algo que se ha tratado de eliminar hasta
ahora.
Las referencias son útiles cuando utilizamos
objetos grandes, esto significa que no se deben
mover en la memoria.
Pero 4 sprites no parecen ofrecer mucho
problema
51. Referencias y clases.
Las referencias son útiles porque hacen posible
crear una jerarquía de clases, donde una nueva
clase hija puede ser creada utilizando los
comportamientos y campos del padre, y además
adicionar los propios.
Cuando la referencia de la instancia es seguida,
el sistema de tiempo de ejecución puede usar los
comportamientos del padre o el hijo como sea
apropiado.
Esto hace mas fácil reusar código cuando
creamos nuevos objetos.
52. La jerarquía en el juego
La clase padre contiene todos los
comportamientos fundamentales.
Las clases hijos, construidas a partir de esa,
adiciona sus propios comportamientos
53. Administración de la jerarquía en
memoria
Todos los datos de una instancia de estructuras
son almacenados en un solo bloque de memoria.
Esto es por que C# proveer una manera de
administrar valores que es necesario acceder tan
eficiente como le sea posible
Sin embargo los datos para los valores de la
clases pueden ser almacenadas en diferentes
lugares, y pueden estar compuesto por
diferentes elementos en la jerarquía de clases.
Esto significa que los datos en las instancias de
clases pueden ser mas lentas de acceder, pero en
la practica esto no es un problema.
54. La clase BaseSprite
Esta clase es la que provee los métodos básicos
y campos de datos
public class BaseSprite
{
protected Texture2D spriteTexture;
protected Rectangle spriteRectangle;
public virtual void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(spriteTexture, spriteRectangle,
Color.White);
}
public virtual void Update(BreadAndCheeseGame game)
{
}
}
55. Otro método de BaseSprite
Estos métodos son usados para establecer los
contenidos de BaseSprite
public class BaseSprite
{
public void LoadTexture(Texture2D inSpriteTexture)
{
spriteTexture = inSpriteTexture;
}
public void SetRectangle(Rectangle inSpriteRectangle)
{
spriteRectangle = inSpriteRectangle;
}
}
56. Usar un sprite base para el fondo
La clase BaseSprite tiene todo los
comportamientos requeridos por el sprite del
fondo.
El fondo no esta animado (es decir, no tiene un
comportamiento update)
Es solo una textura, una posición y el
comportamiento Draw.
Podemos usar la variable BaseSprite para
almacenar el sprite del fondo
57. Crear el TitleSprite desde BaseSprite
El TitleSprite es muy similar a BaseSprite, pero
tiene un comportamiento update que puede
probar el estado del botón A e iniciar el juego si
este es presionado.
Las clases pueden ser creadas para extender la
clase padre y captar todos los comportamientos y
campos del padre.
Usamos la clase BaseSprite como base para
TitleSprite
Esta es una buena idea para rehusar el código
58. La clase TitleSprite completa
Este es el código completo de la clase TitleSprite.
Lo único nuevo que se ha agregado es el método
update, todo lo demás es como la clase padre.
public class TitleSprite : BaseSprite
{
public override void Update(BreadAndCheeseGame game)
{
if (game.GamePad1.Buttons.A == ButtonState.Pressed)
{
game.StartGame();
}
}
}
59. Extender la clase padre
Esto significa extender la clase
La clase TitleSprite ahora contiene un nuevo
método y sobrescribe el existente
public class TitleSprite : BaseSprite
{
public override void Update(BreadAndCheeseGame game)
{
if (game.GamePad1.Buttons.A == ButtonState.Pressed)
{
game.StartGame();
}
}
}
60. Sobrescribir el método de la
padre
La palabra reservada override significa:
“remplazar el comportamiento en la clase padre
con una nueva versión”
Siempre que update es llamado en la instancia
TitleSprite este método es usado en lugar del
originalpublic class TitleSprite : BaseSprite
{
public override void Update(BreadAndCheeseGame game)
{
if (game.GamePad1.Buttons.A == ButtonState.Pressed)
{
game.StartGame();
}
}
}
61. Crear un método virtual
Si se necesita que un método sea sobrescrito,
este debe marcarse como “virtual” en la clase
padre.
C# sabe entonces que el método puede ser
sobrescrito en una clase hija en algún punto.
public class BaseSprite
{
protected Texture2D spriteTexture;
protected Rectangle spriteRectangle;
public virtual void Update(BreadAndCheeseGame game)
{
}
...
}
62. Llamando un método sobrescrito
usando Base
Un método que sobrescribe a otro en un padre,
puede aun necesitar usar algunos
comportamientos del padre.
La palabra “base” provee una manera de realizar
lo que se ha dicho anteriormente
public override void Update(BreadAndCheeseGame game)
{
if (game.GamePad1.Buttons.A == ButtonState.Pressed)
{
game.StartGame();
}
base.Update(game); // call Update in the parent class
}
63. Modificador de acceso protected
Si una clase padre quiere que la clase hija utiliza
los campos de la clase padre, se deben hacer
como protegido.
Esto significa que la clase pueda ver a los
miembros, pero la clase fuera de la jerarquía no.
public class BaseSprite
{
protected Texture2D spriteTexture;
protected Rectangle spriteRectangle;
public virtual void Update(BreadAndCheeseGame game)
{
}
...
}
64. Construir la jerarquía de clases
C# permite extender a una clase hija la jerarquía.
Sin embargo, desde un punto de vista de diseño un
jerarquía no debe ser tan profunda.
Una jerarquía de clases contendrá items que son
esencialmente diferentes versiones de la misma
cosa.
Los sprites son un buen ejemplo de esto.
Las clases de abajo de una jerarquía son las
menos abstractas.
66. Resumen
Las clases contienen métodos y miembros, tal
como las estructuras, pero son administradas por
referencia.
Una referencia provee una conexión a un objeto
en la memoria.
Los programadores pueden crear jerarquías de
clases, en donde las clases hijas se construyen
mediante comportamientos y campos de las
clases padres.
Las clases hijas pueden sobrescribir métodos en
las clase padre.
El modificador de acceso “protected” permite a
las clases hijas tener acceso a los miembros de
la padre.
67. Verdadero o Falso
Las estructuras son administradas por referencia,
por lo que sus contenidos pueden ser accedidos
más rápidamente.
Una clase C# puede extender una estructura C#.
Se puede extender una clase padre una vez.
Si un método es sobrescrito, este debe ser
marcado como virtual en la clase hija.
El acceso a los miembros protegidos de una
clase es registrada cada vez que se utiliza.
68. Verdadero o Falso
Las estructuras son administradas por referencia,
por lo que sus contenidos pueden ser accedidos
más rápidamente.
Una clase C# puede extender una estructura C#.
Se puede extender una clase padre una vez.
Si un método es sobrescrito, este debe ser
marcado como virtual en la clase hija.
El acceso a los miembros protegidos de una
clase es registrada cada vez que se utiliza.
69. Verdadero o Falso
Las estructuras son administradas por referencia,
por lo que sus contenidos pueden ser accedidos
más rápidamente.
Una clase C# puede extender una estructura C#.
Se puede extender una clase padre una vez.
Si un método es sobrescrito, este debe ser
marcado como virtual en la clase hija.
El acceso a los miembros protegidos de una
clase es registrada cada vez que se utiliza.
70. Verdadero o Falso
Las estructuras son administradas por referencia,
por lo que sus contenidos pueden ser accedidos
más rápidamente.
Una clase C# puede extender una estructura C#.
Se puede extender una clase padre una sola vez.
Si un método es sobrescrito, este debe ser
marcado como virtual en la clase hija.
El acceso a los miembros protegidos de una
clase es registrada cada vez que se utiliza.
71. Verdadero o Falso
Las estructuras son administradas por referencia,
por lo que sus contenidos pueden ser accedidos
más rápidamente.
Una clase C# puede extender una estructura C#.
Se puede extender una clase padre una sola vez.
Si un método es sobrescrito, este debe ser
marcado como virtual en la clase hija.
El acceso a los miembros protegidos de una
clase es registrada cada vez que se utiliza.
72. Verdadero o Falso
Las estructuras son administradas por referencia,
por lo que sus contenidos pueden ser accedidos
más rápidamente.
Una clase C# puede extender una estructura C#.
Se puede extender una clase padre una sola vez.
Si un método es sobrescrito, este debe ser
marcado como virtual en la clase hija.
El acceso a los miembros protegidos de una
clase es registrada cada vez que se utiliza.