Sunteți pe pagina 1din 49

Instituto Tecnológico de

Minatitlán
Fundamentos de Programación

M.C. José Ángel Toledo Álvarez

Alumno: Armando Cristóbal Zenteno

Cuestionario Unidad 5

02/06/2008
1. Define el concepto de clase, ilustre su implementación y
de 5 ejemplos de ellos.

Las clases son declaraciones o abstracciones de objetos, lo que significa,


que una clase es la definición de un objeto. Cuando se programa un objeto
y se definen sus características y funcionalidades, realmente se programa
una clase.

Una clase es un contenedor de uno o más datos (variables o propiedades


miembro) junto a las operaciones de manipulación de dichos datos
(funciones/métodos). Las clases pueden definirse como estructuras (struct),
uniones (union) o clases (class) pudiendo existir diferencias entre cada una
de las definiciones según el lenguaje.

La sintaxis típica de una clase es:

class Nombre {
// Variables miembro (habitualmente privadas)
miembro_1; //lista de miembros
miembro_2;
miembro_3;

// Funciones o métodos (habitualmente públicas)


funcion_miembro_1( ); // funciones miembro conocidas
funcion_miembro_2 ( ); // funciones como métodos

// Propiedades (habitualmente públicas)


propiedad_1;
propiedad_2;
propiedad_3;
propiedad_4;
}

Métodos en las clases

Implementan la funcionalidad asociada al objeto. Los métodos son el


equivalente a las funciones en los lenguajes estructurados. Se diferencian
de ellos en que es posible acceder a las variables de la clase de forma
implícita.

Cuando se desea realizar una acción sobre un objeto, se dice que se le


manda un mensaje invocando a un método que realizará la acción.

Habitualmente, los métodos suelen ser verbos.


En Xbase++ los métodos se declaran como:

METHOD Metodo

Propiedades

Las propiedades son un tipo especial de métodos. Debido a que suele ser
común que las variables miembro sean privadas para controlar el acceso y
mantener la coherencia, surge la necesidad de permitir consultar o
modificar su valor mediante pares de métodos: GetVariable y SetVariable.

Los lenguajes orientados a objetos más modernos (por ejemplo Java, C#)
añaden la construcción de propiedad que es una sintaxis simplificada para
dichos métodos:

tipo Propiedad {
get {
}
set {
}
}

En Xbase++ las propiedades de asignación o acceso se declaran:

ACCESS ASSIGN METHOD Metodo VAR Propiedad

...

ACCESS ASSIGN METHOD Clase:Metodo( Propiedad )


::Propiedad:= Propiedad
RETURN::Propiedad

De esta forma es posible realizar operaciones sobre las propiedades como


si fuesen variables normales, el compilador se encarga de crear el código
apropiado que llame a la cláusula get o set según se necesite.

Las propiedades se denominan con nombres como las variables.

2. Explique ampliamente que es un modificador de acceso, para que se


utiliza y que tipos existen
Los modificadores son palabras clave que le entregan al compilador
información acerca de la naturaleza del código, datos o clases.

Los modificadores de acceso son:

public

prívate

protected

Public

Es el acceso mas permisivo. Una clase, variable o método público puede


ser utilizado por cualquier programa Java sin restricción. Un applet esta
declarado como público, de esta forma puede ser instanciado por un
navegador. Una aplicación declara su método main() público para que
pueda ser invocado por el intérprete.

Private

El acceso mas restrictivo es private. Las clases del nivel mas alto no
pueden ser declaradas privadas ya que haría imposible el acceso a
ningún método o variable de esta. Un método o variable privada solo
puede ser instanciado en la clase que lo declara. Las variables y
métodos privados solo pueden ser accedidos por una instancia de la
clase que las declara ya que los modificadores de acceso indican que
clases, no que instancias pueden acceder a sus características. Las
subclases tampoco pueden acceder a variables y métodos privados.

Acceso por defecto

Acceso por defecto es el nombre que le vamos a dar al método de


acceso utilizado por clases, variables y métodos que no tienen
especificado un modificador de acceso.

Las clases, métodos y variables con acceso defecto solo pueden ser
accedidos por clases que se encuentran dentro del mismo paquete.

Aun cuando no se estén programando clases dentro de un paquete, el


compilador de Java considera el directorio donde se encuentran las
clases como un paquete por defecto, de esta forma todas las clases que
se encuentren en este directorio pueden acceder a las clases, métodos y
variables que tienen acceso por defecto.

Protected

Aunque pueda ser mal interpretado, las variables, métodos y clases


declaradas como protegidas son mas accesibles que aquellas que tienen
un acceso por defecto. Tienen acceso a las variables, métodos y clases
protegidas todas aquellas clases que estén dentro del mismo paquete o
sean subclases de la clase.

Subclases y la privacidad de métodos

Java especifica que los métodos no pueden ser sobrescritos para ser más
privados, esto quiere decir que cuando heredamos y realizamos una
sobrecarga o una sobrescritura, el acceso nunca puede ser más
restrictivo. Cualquier método que sea sobrescrito con un acceso más
restrictivo producirá un error de compilación.

Un método puede ser sobrescrito por un método con un acceso diferente


siguiendo algunas reglas:

Un método privado puede ser sobrescrito por un método privado, por


defecto, protegido o público.

Un método por defecto puede ser sobrescrito por un método por defecto,
protegido o público.

Un método protegido puede ser sobrescrito por un método protegido o


público.

Un método público solo puede ser sobrescrito por un método público.

Otros modificadores

Java no tiene en cuenta el orden de aparición de los modificadores.


Declarar una clase public final no es diferente de declararla final public.

No todos los modificadores pueden aplicarse a todo tipo de


característica. Veremos un detalle de esto.

final

El modificador final se aplica a clases, métodos y variables. El significado


de final varia de contexto a contexto, pero la idea en si es la misma, la
característica no puede ser cambiada. Esto quiere decir que de una clase
final no se puede derivar otra clase, una variable final no puede ser
modificada una vez que se le ha asignado el valor y un método final no
puede ser sobrescrito.

Aunque una variable final no puede ser cambiada, su contenido puede


ser modificado. Si esta variable apunta a un objeto, es perfectamente
válido modificar las propiedades del objeto.

abstract

El modificador abstract puede ser aplicado a clases y métodos. Una clase


que es abstracta no puede ser instanciada (esto es, no se puede llamar a
su constructor). Las clases abstractas se pueden utilizar como
mecanismo para trasladar la implementación de los métodos a la
subclase. De esta forma, para poder utilizar una clase abstracta se tiene
que derivar y se tienen que implementar los métodos abstractos
definidos en ellas. El compilador obligará a implementar todos los
métodos abstractos de la clase o declarar la clase derivada abstracta. Si
una clase tiene uno o mas métodos abstractos el compilador insiste en
que se debe declarar abstracta. También debe ser abstracta la clase si
hereda uno o mas métodos abstractos para el cual no provee
implementación o si la clase declara una interface pero no proporciona
implementaciones para cada uno de sus métodos.

static

Este modificador puede ser aplicado a variables, métodos e inclusive a


cierto código que rompe un poco las reglas del lenguaje y que no es
parte de un método. Se puede pensar que una característica estática
esta asociada a la clase en lugar de a la instancia individual de la clase.

Esto quiere decir que para una variable animales existe solo una variable
animales para todas las instancias de la clase. Se puede hacer referencia
a una variable estática mediante una instancia de la clase o mediante el
nombre de la clase.

Los métodos al igual que los datos, pueden ser declarados estáticos. Los
métodos estáticos solo pueden utilizar características estáticas y llamar
a métodos estáticos. Estos pueden ser invocados incluso antes de que
alguna instancia de la clase sea construida.

No es posible acceder a una variable de instancia o a un método de


instancia dentro de un método estático. Al igual que las variables
estáticas, los métodos estáticos no están asociados a una instancia
individual de su clase.
Si un método estático necesita acceder a una variable no estática o
llamar a un método no estático, debe especificar que instancia de su
clase es dueña de la variable o ejecutar el método.

Un método estático no puede ser sobreescrito de tal forma de que deje


de ser estático.

Resumiendo, un método estático solo puede acceder a datos estáticos


de su clase y no puede acceder a métodos no estáticos. Un método solo
puede llamar los métodos estáticos de su clase y no puede llamar a
métodos no estáticos. Un método estático no tiene la variable this y no
puede ser sobreescrito con un método no estático

Inicializadores estáticos

Es legal para una clase contener código estático fuera del método de un
cuerpo. Una clase puede tener un bloque de código de inicialización
simplemente rodeado de llaves con la palabra estatic.
public class Gallina {

static int patas=2;

static {

System.out.prinln("Tengo " + patas + " patas.");

public static void main(String args[]) {

System.out.println("Programa.");

Este código es ejecutado exactamente una sola vez cuando la clase es


cargada en el orden en que esta escrito sin importar cuantos bloques
haya. Hay que prestar mucha atención con este tipo de construcciones y
debe ser utilizado con precaución ya que el abuso puede resultar en
código confuso y poco claro.

native
Este modificador solo puede referirse a métodos, indica que el cuerpo de
un método se encuentra fuera de la máquina virtual de Java, en una
librería. El código nativo esta escrito en otro lenguaje de programación,
típicamente C o C++ y compilado para una sola plataforma por lo que la
independencia de plataforma de Java es violada cuando utilizamos este
tipo de métodos.

transient

El modificador transient es solo aplicado a variables. Una variable


transient no es almacenada como parte del estado persistente de su
objeto.

Muchos objetos que son declarados con interfases Serializable o


Externalizable pueden tener su estado serializado y escribir a destinos
fuera de la máquina virtual. Esto se logra pasando el objeto a el método
writeObject() de la clase ObjectOutputStream. Si el objeto es pasado a
un FileOutputStream, entonces el estado del objeto es escrito en un
fichero. Si el objeto es pasado a un socket OutputStream, entonces el
estado del objeto será escrito en una red. En ambos casos el objeto
puede ser reconstruido leyendo de un ObjectInputStream.

Cuando hay cierta información que no se desea enviar como parte del
objeto, como puede ser cierta información delicada que quizás por
razones de seguridad no deben ser enviadas a través de un canal
inseguro (una contraseña), se declara transient y esta no es escrita
durante la serialización.

synchronized

Este modificador es utilizado para controlar el acceso a código crítico en


programas de hilado múltiple. En artículos siguientes hablaremos en mas
detalle de este modificador ya que es casi imprescindible su uso cuando
utilizamos hilado múltiple y debemos acceder a propiedades o recursos
desde varios hilos a la vez.
volatile

Este modificador solo lo mencionaremos para completar la lista. Solo las


variables pueden ser declaradas volatile. Esto quiere decir que pueden
ser modificadas de forma asincrónica para que el compilador tome las
precauciones necesarias. Este tipo de variables tiene especial interés
para los ambientes con varios procesadores ya que cuando un hilo
modifica una variable de un objeto, este puede tener una copia local de
la variable y modificar esta. El problema surge cuando otro hilo lee la
variable y el valor recibido es el de la variable local al hilo. Esta puede
diferir de la variable local del otro hilo e inclusive de la variable
almacenada en una suerte de "memoria principal". Al especificar la
variable como volatile se le indica a el compilador que la variable debe
ser leída y escrita directamente de la "memoria principal" cada vez que
se necesita evitando tener copias locales distintas.

3. De los diferentes tipos de modificadores de acceso ilustre 5


ejemplos de aplicación para cada uno de ellos de manera
independiente

Modificador public

Es el nivel de acceso más permisivo. Sirve para indicar que el método o


atributo de la clase es público. En este caso se puede acceder a ese
atributo, para visualizarlo o editarlo, por cualquier otro elemento de
nuestro programa. Es el modificador que se aplica si no se indica otra cosa.

Veamos un ejemplo de clase donde hemos declarado como public sus


elementos, un método y una propiedad. Se trata de la clase "dado", que
tiene un atributo con su puntuación y un método para tirar el dado y
obtener una nueva puntuación aleatoria.

class dado{
public $puntos;

function __construct(){
srand((double)microtime()*1000000);
}

public function tirate(){


$this->puntos=$randval = rand(1,6);
}
}

$mi_dado = new dado();

for ($i=0;$i<30;$i++){
$mi_dado->tirate();
echo "<br>Han salido " . $mi_dado->puntos . " puntos";
}

// protected_public.cs
// Public access
using System;
class Point
{
public int x;
public int y;
}
class MainClass
{
static void Main()
{
Point p = new Point();
// Direct access to public members:
p.x = 10;
p.y = 15;
Console.WriteLine("x = {0}, y = {1}", p.x, p.y);
}

public class:
public class Tricycle
{
// protected method:
protected void Pedal() { }

// private field:
private int m_wheels = 3;

// protected internal property:


protected internal int Wheels
{
get { return m_wheels; }
}
}

namespace System.IO
{
public class Stream {...}
public class FileStream: Stream { ... }
...
}

Assembly A2.dll

namespace EnsambladoGuille
{
public class GuilleStream : Stream {...}
}

y el siguiente trozo de código:

using System.IO;
using EnsambladoGuille;

class Program
{
static void Main()
{
Stream s = new GuilleStream();
...
}
}

class Myclass1 //nombre de clase


{
public int X; //Variables con modificador
public int Y; //public
}
class Myclass2 //nombre de clase
{
public static void Main()
{
Myclass1 mc1 = new Myclass1(); //Creacion de objetos
mc1.x=10; //inicializando con
mc1.y=15; // valores por el programador
Console.WriteLine(" x={0}, y={1}",mc1.x,mc1.y); //Despliegue de datos
}
}
PRIVATE
el modificador de acceso de los miembros de una clase privado
corresponde al nivel mas restrictivo.Los miembros privados solo son
accesibles dentro del cuerpo de la clase que lo declara.

Ejemplo:
class Employer //nombre de clase
{
public string name="xxx"; //Declaracion de
private double salary=1000.00; //variables con modificador
public double AccesSalary() //public y privated
{
return salary;
}
}
class Mainclass
{
public static void Main()
{
Employer E = new Employer(); //creacion de objeto
string n = E.name;
double s = E.Acces
Console.WriteLine(" nombre:{0}",n); //Despliegue de
Console.WriteLine(" salario:{0}",s); //datos
Console.ReadLine();
}

class dado{
private $puntos;

function __construct(){
srand((double)microtime()*1000000);
}

private function tirate(){


$this->puntos=$randval = rand(1,6);
}

public function dame_nueva_puntuacion(){


$this->tirate();
return $this->puntos;
}
}

$mi_dado = new dado();


for ($i=0;$i<30;$i++){
echo "<br>Han salido " . $mi_dado->dame_nueva_puntuacion() . "
puntos";
}

package privateTest
{
import flash.util.trace

public class HasPrivateMethod


{
function HasPrivateMethod( )
{
trace( "HasPrivateMethod.constructor" );
}

internal function internalMethod( )


{
trace( "HasPrivateMethod.internalMethod( )" );
}

protected function superMethod( )


{
trace( "HasPrivateMethod.superMethod" );
}

private function privateMethod( )


{
trace( "HasPrivateMethod.privateMethod" );
}
}
}
package privateTest
{
public class SubClass extends HasPrivateMethod
{
function SubClass( )
{
trace( "Subclass.constructor" );
}

public function init( )


{
//Método internal de la superclase
internalMethod( );

//Método protected de la superclase


superMethod( );

//Método private de la superclase. Error de


compilación
privateMethod( );

}
}

// public class:
public class Tricycle
{
// protected method:
protected void Pedal() { }

// private field:
private int m_wheels = 3;

// protected internal property:


protected internal int Wheels
{
get { return m_wheels; }
}
}

Modificador protected

Este indica un nivel de acceso medio y un poco más especial que los
anteriores. Sirve para que el método o atributo sea público dentro del
código de la propia clase y de cualquier clase que herede de aquella donde
está el método o propiedad protected. Es privado y no accesible desde
cualquier otra parte. Es decir, un elemento protected es público dentro de
la propia clase y en sus heredadas.

Más adelante explicaremos la herencia y podremos ofrecer ejemplos con el


modificador protected.

package privateTest
{
import flash.util.trace

public class HasPrivateMethod


{
function HasPrivateMethod( )
{
trace( "HasPrivateMethod.constructor" );
}

internal function internalMethod( )


{
trace( "HasPrivateMethod.internalMethod( )" );
}

protected function superMethod( )


{
trace( "HasPrivateMethod.superMethod" );
}

private function privateMethod( )


{
trace( "HasPrivateMethod.privateMethod" );
}
}
}

class B : A
{
public B()
{

}
private string _text = "Adiós";
private int _count = 0;
new public string Text
{
get { return _text; }
protected set { _text = value; }
}
new protected int Count
{
get { return _count; }
set { _count = value; }
}
}
}
class Empleado {
protected int sueldo;
...
}

public class Object {


public final Class getClass() { . . . }
public String toString() { . . . }
public boolean equals(Object obj) { . . . }
public int hashCode() { . . . }
protected Object clone() throws CloneNotSupportedException { . . . }
public final void wait() throws IllegalMonitorStateException,
InterruptedException { . . . }
public final void wait(long millis) throws
IllegalMonitorStateException,
InterruptedException {. . .}
public final void wait(long millis, int nanos) throws
IllegalMonitorStateException,
InterruptedException { . . . }
public final void notify() throws IllegalMonitorStateException { . . . }
public final void notifyAll() throws
IllegalMonitorStateException { . . . }
protected void finalize() throws Throwable { . . . }
}

package package2;
class AccesoPorPaquete{
void accederAUnMiembro(){
ClaseConMiembroProtegido cc = new
ClaseConMiembroProtegido();
System.out.println(cc.demeAlgo());
}
}

4. Explique ampliamente en que consiste el concepto de


encapsulamiento de la clase

El principio de encapsulamiento es una forma moderna de denominar al


tradicional principio de ocultamiento de la información. El principio nos
indica que debemos hacer que los detalles de la clase estén ocultos para
el exterior (también se denomina implementación encapsulada).
Cada objeto está aislado del exterior, es un módulo natural, y la
aplicación entera se reduce a un agregado o rompecabezas de objetos.
El aislamiento protege a los datos asociados a un objeto contra su
modificación por quien no tenga derecho a acceder a ellos, eliminando
efectos secundarios e interacciones.

De esta forma el usuario de la clase puede obviar la implementación de


los métodos y propiedades para concentrarse sólo en cómo usarlos. Por
otro lado se evita que el usuario pueda cambiar su estado de maneras
imprevistas e incontroladas.

La utilidad del encapsulamiento va por la facilidad para manejar la


complejidad, ya que tendremos a las Clases como cajas negras donde
sólo se conoce el comportamiento pero no los detalles internos, y esto es
conveniente porque nos interesará será conocer qué hace la Clase pero
no será necesario saber cómo lo hace.

El encapsulamiento es el principio por el cual se ocultan los detalles de


implementación al usuario.
Cada clase tiene dos partes:
· El Interfaz es la parte pública con la que interactúa el usuario
(métodos públicos)
· La Implementación es el código que realiza todas las operaciones de
la clase (métodos privados)

5. Ilustre 5 ejemplos diferentes donde usted utilice el


encapsulamiento de la clase, explicando cual es la clase y cuales
son los elementos que se están encapsulando

class Casilla extends Button // clase

boolean descubierta; //objeto encapsulado

Casilla(String t) //objeto encapsulado

super.setLabel(t); //objeto encapsulado

setBackground(new Color(200,200,200)); //objeto encapsulado

setFont(new Font ("Comic Sans MS", Font.BOLD, 20)); //objeto


encapsulado

descubierta = false; //objeto encapsulado


}

protected Arboles(Object arbol,boolean enArchivo)//clase

this.arbol=arbol; //objeto encapsulado

this.enArchivo=enArchivo; //objeto encapsulado

class CargandoArchivos extends Thread{ //clase

protected ListadorArchivos listadorArchivos; //objeto encapsulado

private File archivo; //objeto encapsulado

CargandoArchivos(ListadorArchivos listadorArchivos,File archivo){

this.listadorArchivos=listadorArchivos; //objeto encapsulado

this.archivo=archivo; //objeto encapsulado

class Operación //clase

int a, b, c; //objeto encapsulado

a = b + c; //objeto encapsulado

BufferedReader dato = new BufferedReader (new InputStreamReader


(System.in));

BufferedReader dato1 = new BufferedReader (new InputStreamReader


(System.in));

System.out.println(“Introduce el valor de b”);

dato.readLine();
System.out.println(“Introduce el valor de c”);

dato.readLine();

System.out.println(“la suma de b + c es “+a);

public class Rectangulo extends Geometria { //clase

private static int numRectangulos = 0; //objeto encapsulado

protected double x1, y1, x2, y2; //objeto encapsulado

public Rectangulo (double p1x, double p1y, double p2x, double p2y) {

x1 = p1x;

x2 = p2x;

y1 = p1y;

y2 = p2y;

numRectangulos++; //objeto encapsulado

public Rectangulo(){ this(0, 0, 1.0, 1.0); } //objeto encapsulado

public double perimetro() { return 2.0 * ((x1-x2)+(y1-y2)); }

public double area() { return (x1-x2) * (y1-y2); }

6. Explique ampliamente como se comunican los elementos que


forman parte de un programa orientado a objeto

Un objeto es la unidad individual que en tiempo de ejecución realiza las


tareas de un programa. Estos objetos interactúan unos con otros, en
contraposición a la visión tradicional en la cual un programa es una
colección de subrutinas (funciones o procedimientos), o simplemente una
lista de instrucciones para el computador. Cada objeto es capaz de
recibir mensajes, procesar datos y enviar mensajes a otros objetos de
manera similar a un servicio.
Los objetos son unidades independientes que se comunican entre ellos
mediante mensajes.
Un objeto es inútil si está aislado. El medio empleado para que un objeto
interactúe con otro son los mensajes. Hablando en términos un poco más
técnicos, los mensajes son invocaciones a los métodos de los objetos.
Estas interacciones suponen ciertos tipos de relaciones entre los objetos del
sistema. La semántica que expresa un objeto en el sistema está
determinado en primer lugar, por las relaciones que éste establece con
otros objetos o conjunto de objetos. Tomemos como ejemplo un objeto
fecha, del que sin establecer ningún tipo de relación, podría decirse
que significa un día del año particular. Pero si relacionamos ese objeto fecha
con un objeto Persona de manera que represente la fecha en que esa
persona nació, en ese contexto dado, el mismo objeto fecha adoptaría un
significado diferente, el de un cumpleaños, aunque sigue siendo una fecha,
ahora tiene otra idea asociada. Las relaciones entre objetos no solo están
definidas por los objetos que participan y la circunstancia que los relaciona,
sino también por la cantidad de objetos (cardinalidad de la relación) y la
dirección de la misma. Una relación puede tener cardinalidad:

 uno a uno, ejemplo: un auto tiene un motor


 uno a muchos, ejemplo: un auto tiene muchas ruedas
 muchos a muchos, ejemplo: un auto se puede servir en
muchas gasolineras y una gasolinera puede servir a muchos autos.

y direccionalidad:

 unidireccional, ejemplo: un auto tiene cuatro ruedas.


 bidireccional

Las relaciones entre objetos más generales son las siguientes:

Composición

La composición (también conocida como relación asociativa) es un tipo de


relación que se establece entre dos objetos que tienen comunicación
persistente. Se utiliza para expresar que un par de objetos tienen una
relación de dependencia para llevar a cabo su función, de modo que uno de
los objetos involucrados está compuesto por el otro.
De manera práctica, es posible reconocer asociatividad entre dos objetos A
y B si la proposición "A tiene un B" (o viceversa) es verdadera. Por ejemplo:
"una computador tiene un disco duro" es verdadero, por tanto un objeto
computador tiene una relación de composición con al menos un objeto disco
duro.
Uso
Un objeto usa (conoce) a otro cuando puede enviarle mensajes, por
ejemplo, para requerir de este algún servicio. La composición puede verse
como un caso particular de esta relación.
Delegación
En ocasiones para lograr flexibilidad de diseño, un objeto es implementado
de forma tal que este delegue parte de su funcionalidad en otro objeto. Esto
es muy común en aplicaciones que hacen uso de interfaces graficas de
usuario, en las que los controles gráficos generales delegan la acción que se
ejecutará ante determinado estímulo en otro objeto.
7. Define el concepto de método y explica ampliamente para que
sirve y como se utiliza

Utilizado principalmente en programación orientada a objetos, el término


se refiere a las porciones de código asociadas exclusivamente con una
clase (se los denomina entonces métodos de clase o métodos estáticos) o
con un objeto (en este caso métodos de instancia). Análogamente a los
procedimientos en los lenguajes imperativos, un método consiste
generalmente de una serie de sentencias para llevar a cabo una acción, un
juego de parámetros de entrada que regularán dicha acción y,
posiblemente, un valor de salida (o valor de retorno) de algún tipo. El
propósito de los métodos es el de proveer un mecanismo para acceder
(leer o modificar) los datos privados que se encuentran almacenados en un
objeto o clase.

Algunos lenguajes de programación asumen que un método debe de


mantener el invariante del objeto al que está asociado asumiendo también
que éste es válido cuando el método es invocado. En lenguajes compilados
dinámicamente, los métodos pueden ser objetos de primera clase, y en
este caso se puede compilar un método sin asociarse a ninguna clase en
particular, y luego asociar el vínculo o contrato entre el objeto y el método
en tiempo de ejecución. En cambio en lenguajes no compilados
dinámicamente o tipados estáticamente, se acude a precondiciones para
regular los parámetros del método y postcondiciones para regular su salida
(en caso de tenerla). Si alguna de las precondiciones o postcondiciones es
falsa el método genera una excepción. Si el estado del objeto no satisface
la invariante de su clase al comenzar o finalizar un método, se considera
que el programa tiene un error de programación.

La diferencia entre un procedimiento (generalmente llamado "función" si


devuelve un valor) y un método es que éste último, al estar asociado con
un objeto o clase en particular, puede acceder y modificar los datos
privados del objeto correspondiente de forma tal que sea consistente con el
comportamiento deseado para el mismo. Así, es recomendable entender a
un método no como una "secuencia de instrucciones" sino como "la forma
en que el objeto es útil" (el método para hacer su trabajo). Por lo tanto,
podemos considerar al método como el pedido a un objeto para que realice
una tarea determinada o como la vía para enviar un mensaje al objeto y
éste reacciona acorde a dicho mensaje.

Como ya se mencionó, los métodos de instancia están relacionados con un


objeto en particular, mientras que los métodos estáticos o de clase
(también denominados métodos compartidos) están asociados a una clase
en particular. En una implementación típica, a los métodos de instancia se
les pasa una referencia oculta al objeto al que pertenecen, comúnmente
denominada this o self (referencias a sí mismo por sus significados en
inglés), para que puedan acceder a los datos asociados con el mismo. Un
ejemplo típico de un método de clase sería uno que mantuviera la cuenta
de la cantidad de objetos creados dentro de esa clase.

Algunos lenguajes de programación requieren la definición de


constructores, siendo estos métodos de instancia especiales llamados
automáticamente cuando se crea una instancia de alguna clase. En Java y
C++ se distinguen por tener el mismo nombre de la clases a la que están
asociados. Lenguajes como Smalltalk no requieren constructores ni
destructores.

Los métodos de acceso son un tipo de método normalmente pequeño y


simple que se limita a proveer información acerca del estado de un objeto.
Aunque introduce una nueva dependencia, la utilización de métodos es
preferida a acceder directamente a la información para proveer de una
nueva capa de abstracción (programación orientada a objetos). Por
ejemplo, si una clase que modela una cuenta bancaria provee de un
método de acceso "ObtenerBalance()" en versiones posteriores de la clase
se podría cambiar el código de dicho método substancialmente sin que el
código dependiente de la clase tuviese que ser modificado (un cambio sería
necesario siempre que el tipo de dato devuelto por el método cambie). Los
métodos de acceso que pueden cambiar el estado de un objeto son
llamados, frecuentemente, métodos de actualización ó métodos de
mutación; a su vez, los objetos que proveen de dichos métodos son
denominados óbjetos mutables.
Una operación que realiza acceso a los datos. Podemos definir método
como un programa procedimental o procedural escrito en cualquier
lenguaje, que está asociado a un objeto determinado y cuya ejecución sólo
puede desencadenarse a través de un mensaje recibido por éste o por sus
descendientes.
Son sinónimos de 'método' todos aquellos términos que se han aplicado
tradicionalmente a los programas, como procedimiento, función, rutina,
etc. Sin embargo, es conveniente utilizar el término 'método' para que se
distingan claramente las propiedades especiales que adquiere un programa
en el entorno OOP, que afectan fundamentalmente a la forma de invocarlo
(únicamente a través de un mensaje) y a su campo de acción, limitado a un
objeto y a sus descendientes, aunque posiblemente no a todos.
Si los métodos son programas, se deduce que podrían tener argumentos, o
parámetros. Puesto que los métodos pueden heredarse de unos objetos a
otros, un objeto puede disponer de un método de dos maneras diferentes:
-Métodos propios. Están incluídos dentro de la cápsula del objeto.
-Métodos heredados. Estan definidos en un objeto diferente, antepasado de
éste (padre,"abuelo", etc.). A veces estos métodos se llaman métodos
miembro porque el objeto los posee por el mero hecho de ser miembro de
una clase.

Utilice una interfaz cuando:


• Haya un grupo de métodos relacionados a los que se pueda llamar.
• Una clase sólo necesita una implementación del método.
• La clase que utiliza la interfaz deseará convertir esa interfaz en otra
interfaz o tipos de clase.
• El método que se va a implementar está vinculado al tipo o identidad de la
clase; por ejemplo, métodos de comparación.

Un buen ejemplo del uso de una interfaz de método único en lugar de un


delegado es IComparable o IComparable. IComparable declara el método
CompareTo, que devuelve un entero que especifica una relación menor
que, igual que o mayor que entre dos objetos del mismo tipo.
IComparable se puede utilizar como base de un algoritmo de ordenación
y, aunque el uso de un método de comparación de delegados como base
de un algoritmo de ordenación sería válido, no es la opción ideal. Lo ideal
es una interfaz de método único, ya que la capacidad de establecer
comparaciones pertenece a la clase, y el algoritmo de comparación no
cambia en tiempo de ejecución.

8. Tomando ejemplos de programación 5 programas diferentes,


ilustre como funciona los métodos que se utilizan en cada
programa

Ésta es la forma general de un método:

tipo nombre_del_método(lista de parámetros) {

// cuerpo del método


}

Para hacerlo introduciremos un método en dicha clase:

/* Un programa que incluye un método en la clase Cubo */

class Cubo {
double ancho;
double alto;
double largo;

void volumen(){
System.out.print("Volumen igual a : ");
System.out.println(ancho * alto * largo);
}

}
// esta clase declara un objeto de tipo Cubo

class CuboDemo{

public static void main(String args[]){


Cubo micubo = new Cubo();
double vol;

// asignación de valores de la variables de instancia de micubo


micubo.ancho = 10;
micubo.alto = 20;
micubo.largo = 15;

// cálculo de volumen de Cubo


micubo.volumen();
}

/* Un programa que incluye un método en la clase Cubo */

class Cubo {
double ancho;
double alto;
double largo;

double volumen(){
return(ancho * alto * largo);
}

// esta clase declara un objeto de tipo Cubo

class CuboDemo{

public static void main(String args[]){


Cubo micubo = new Cubo();
double vol;

// asignación de valores de la variables de instancia de micubo


micubo.ancho = 10;
micubo.alto = 20;
micubo.largo = 15;

// cálculo de volumen de Cubo


vol = micubo.volumen();
System.out.println("Volumen igual a : "+ vol);
System.out.println("Volumen igual a : "+ micubo.volumen());
System.out.println();// estas sentencias son equivalentes.

Ahora es un método de propósito general que puede cálcular el cuadrado de


cualquier número entero, no solo de 10.

int v1, v2;


v1 = cuadrado(5); // igual a 25
v1 = cuadrado(9); // igual a 81
v2 = 2;
v1 = cuadrado(v2); // igual a 4

9. Explique ampliamente cuales son las reglas sintácticas (reglas


para escribir correctamente las expresiones) que se utilizan para
comunicarse a través de los métodos

Para un inexperto, la forma en que se combinan las palabras y símbolos


para formar programas ejecutables puede parecer confusa y casi
antojadiza. Sin embargo, la escritura de programas computacionales se rige
por un reducido conjunto de reglas gramaticales. Este conjunto de reglas se
denomina la sintaxis del lenguaje de programación. Por esta razón, también
se habla de reglas sintácticas como sinónimo de reglas gramaticales.
Las reglas gramaticales son similares a sus contrapartes de los lenguajes
hablados. La diferencia radica en que en un lenguaje hablado una frase
gramaticalmente mal formada, una persona es capaz de comprender. Al
contrario, en un lenguaje de programación, cualquier descuido en el
cumplimiento de su gramática o sintaxis se traduce en un mensaje de error,
y por lo tanto, un programa que no funciona.
Por ejemplo, la siguiente instrucción:

a+1 = b;

podría ser interpretada como calcular a+1 y asignársela a b. Pero el


compilador es incapaz de captar esta interpretación y termina con un
mensaje de error.
Por esta razón, es sumamente importante dominar la gramática del
lenguaje que se usa para programar. Su conocimiento, permite comprender
más rápidamente los errores que se cometerán inevitablemente al escribir
un programa. Tales errores serán típicamente comunicados por el
compilador en un lenguaje rudo y críptico.
A lo largo del curso, hemos descrito estas reglas gramaticales. Sin
embargo, éste es un buen momento para repasar tales reglas y verlas
como un todo. También aprovecharemos el momento para presentar
nuevas reglas no vistas hasta el momento.
Cada lenguaje de programación posee su propia sintaxis. Las reglas que
rigen para Java, no son las mismas que para Pascal o Visual Basic. Por
razones de tiempo, en este curso solo veremos en profundidad las reglas
del lenguaje Java. La buena noticia es que una vez que se entiende la
sintaxis de un lenguaje específico, es muy fácil aprender la sintaxis de
otros lenguajes de programación.

Categorías sintácticas
Las reglas gramaticales que constituyen la sintaxis de un lenguaje se basan
en la existencia de categorías sintácticas. Por ejemplo, en
Java, instrucciones, expresiones, asignaciones, etc. son ejemplos de
categorías sintácticas de la misma forma que las proposiciones, los verbos,
los sustantivos, son categorías sintácticas en un lenguaje hablado como el
castellano.
Cuando una regla gramatical especifica que en tal contexto debe ir tal
categoría sintáctica, significa que ahí puede y debe ir cualquier
construcción del lenguaje que sea considerada de esa categoría.
Para el caso específico del lenguaje Java, las categorías sintácticas más
importantes son las siguientes:

identificadores.
constantes.
operadores binarios y unario.
expresiones.
instrucciones.
Reglas sintácticas
La sintaxis de un lenguaje permite determinar matemáticamente si un
programa es correcto desde el punto de vista sintáctico o no. Esta sintaxis
se expresa en base a un conjunto de reglas gramaticales del estilo:
exp -> exp op-bin exp

En donde exp y op-bin son abreviaciones de las categorías


sintácticas expresión y operador binario (un símbolo que denota una
operación entre dos valores).
Lo que aparece a la izquierda del símbolo -> es el nombre de la categoría
sintáctica que se pretende describir. A la derecha se indica una de las
formas de construir frases del lenguaje que pertenecen a esa categoría. La
regla sintáctica anterior se lee como: una expresión puede ser construida a
partir de otra expresión seguida de un operador binario y luego una tercera
expresión.
Una sola regla gramatical no basta para describir lo que es una expresión.
No todas las expresiones se construyen en base a operaciones sobre otras
expresiones. La siguientes reglas indican que una constante o un
identificador también son expresiones.
ex -> con
p st
-> ide
nt
En donde const es la abreviación para una constante e ident es un
identificador.
(Obs.: en la última regla sintáctica se ha omitido la categoría
sintáctica exp con el objeto de aligerar la notación.)
También se necesita describir qué es un operador binario. Esto se hace
mediante las siguientes reglas gramaticales:
op- -
+
bin >
-
-
>
-
*
>
-
/
>
-
%
>

Arbol sintáctico
Una árbol sintáctico permite demostrar que una secuencia de caracteres es
una determinada categoría sintáctica. Por ejemplo, el siguiente es un árbol
sintáctico que demuestra que 'a+5' es una expresión:
a + 5
| | |
ident op-bin const
| | |
exp | exp
\ | /
\ | /
exp

Para que un árbol sintáctico sea válido se necesita que para cada
bifurcación del estilo:
sub-categorías ...
\ | /
categoría

exista la siguiente regla sintáctica:

categorí -> sub-


a categorías ...

Por ejemplo la siguiente bifurcación:


exp op-bin exp
\ | /
\ | /
exp

es posible gracias a que existe la regla:

ex -> exp op-bin


p exp

El principio básico de la sintaxis consiste en que una frase corresponde a


una categoría sintáctica determinada, sí y solo sí (i) es posible construir un
árbol sintáctico en donde en la raíz aparezca la categoría sintáctica
pretendida y (ii) la lectura secuencial de las hojas corresponde a la frase
original.

La secuencia 'a+b*c' también es una expresión, puesto que su árbol


sintáctico es:
a + b * c
| | | | |
ident | ident | ident
| | | | |
| | exp op-bin exp
| | \ | /
exp op-bin exp
\ \ /
\ \ /
exp
En general, basta construir un sólo arbol sintáctico para demostrar que una
frase corresponde a la categoría que aparece en la raíz. Si no es posible
construir este árbol, entonces la frase no corresponde a esa categoría. Por
ejemplo, no es posible construir un árbol sintáctico que muestre que 'a + b
c' es una expresión.

Sin embargo, con las reglas que hemos enunciado para una expresión
hasta el momento, no podemos mostrar que '-a + b' es una expresión. El
siguiente grupo de reglas sintácticas permite enriquecer el conjunto de
frases que corresponden a expresiones:

Expresiones

ex (1
-> const
p )
(2
-> ident
)
-> op-unario (3
exp )
-> exp op-bin (4
exp )
(5
-> ( exp )
)
Operadores binarios
aritmético op- - +
s: bin >
- -
>
- *
>
- /
>
- %
>
relacional - ==
es: >
- !=
>
- >=
>
- <=
>
- >
>
- <
>
booleanos - &&
: >
- ||
>

Operadores unarios
aritmétic op- - -
os: unario >
- +
>
booleano - !
s: >

Hemos enumerado las reglas que describen lo que es una expresión para
indicar cuando se aplican en los árboles sintácticos que mostrares a
continuación:

• -a + b
• - a + 5
• | | | |
• op-unario ident op-bin const
• \ | | |
• \ exp(2)/ exp(1)
• \ / / /
• exp(3) / /
• \ / /
• --+-------
• |
• exp(4)
• a-(b-c)
• a - ( b - 5 )
• | | | | | | |
• ident op-bin | ident op-bin const |
• | | | | | | |
• exp(2) | | exp(2) | exp(1)|
• \ \ \ \ | / /
• \ \ \ ---+---- /
• \ \ \ exp(4) /
• \ \ \ | /
• \ \ -----+-------
• \ \ exp(5)
• \ \ /
• -----\----
• exp(4)
• a+-b
• a + - b
• | | | |
• ident | op-unario ident
• | | \ /
• | | \ exp(2)
• | | \ /
• exp(2) op-bin exp(3)
• \ | /
• ----|--------
• exp(4)

Del mismo modo, se puede mostrar que 'a+!b' también es una expresión.
Para ello basta cambiar el '-' por '!' en el árbol anterior. Sin embargo, aún
cuando sintácticamente se trate de una expresión bien escrita, es una
expresión incorrecta, puesto que no es posible asignarle un tipo a esta
expresión. Esto quedará más claro cuando hablemos sobre el sistema de
tipos.

Ejercicios:

Construya un arbol sintáctico del la siguiente expresión:

-(a+-5*b)

Para cada expresión que aparezca en el árbol, indique el número de la regla


que justifica esa bifurcación.

En el siguiente árbol hay dos errores. Indique cuáles son:

• a + 5 c
• | | | |
• ident | const ident
• | | | |
• | | exp exp
• | | \ /
• exp | exp
• \ | /
• ---|------
• exp

Reglas de desambiguación

El árbol sintáctico no sólo muestra que una frase es una expresión, si no


que además indica cuál es la parentización que usará el compilador para
evaluar la expresión. Por ejemplo, más arriba se vio un árbol sintáctico para
la expresión 'a-b*c'. En ese árbol se formaba una sub-expresión a partir de
'b*c'. Al tomar esa decisión se manifiesta que primero se evalúa b*c y
luego a + (b*c).

El problema es que esta expresión posee un segundo árbol sintáctico:


a - b * c
| | | | |
ident op-bin ident op-bin ident
\ | / / /
exp | exp / exp
\ | / / /
exp / /
\ / /
--+-----
exp

En este otro árbol, se calcula 'a-b' y el resultado se multiplica por c, lo que


claramente es distinto de lo anterior. Este tipo de expresiones son entonces
ambiguas. El lenguaje hablado está típicamente plagado de ambiguedades
que a veces causan problemas de interpretación. Sin embargo, un lenguaje
computacional no puede ser ambiguo.

Por esta razón, los lenguajes de programación incluyen además de las


reglas sintácticas, reglas de desambiguación que le dan un sentido único a
las expresiones como la anterior. Estas reglas son las siguientes:

Precedencia

Indica qué operadores tienen precedencia al momento de construir el árbol


sintáctico. En Java, las prioridades son las siguientes:

- +
(operadores
unarios)
* / %

+ -
(operadores
binarios)
== != >= <= > <
!
&& ||
Estas reglas eliminan el segundo árbol sintáctico como posible
interpretación. Java interpreta inequívocamente la expresion 'a-b*c' por
medio del primer árbol sintáctico.

• Asociatividad

Indica como parentizar en caso de operadores de la misma precedencia. En


Java casi todos los operadores se parentizan de izquierda a derecha. Esto
significa que:
a+b+c es equivalente a (a+b)+c

Con las reglas de desambiguación toda expresión tiene un único árbol


sintáctico válido.

La expresión de asignación

En Java la asignación es una expresión como cualquier otra y por lo tanto


se puede colocar válidamente en cualquier lugar en donde deba ir una
expresión. La regla sintáctica que describe la asignación es la siguiente:
ex -> ident =
p exp

Con esta regla, la siguiente expresión está sintácticamente bien escrita:


a= b= 0 o equivalentemente: a= (b= 0)

Su significado semántico también es correcto: la expresión 'b=0' indica que


se asigna 0 a la variable b. El resultado de esa expresión es el mismo valor
asignado, es decir 0. Ese mismo valor se asigna luego a la variable a.

Este tipo de construcciones puede ser útil para realizar varias


inicializaciones en una misma línea:
a= b= c= d= e= 0

Gracias a que la asignación es una expresión, también es posible escribir:


...
while ( (a= readInt())!=0 ) {
...
}

en vez de:

a= readInt();
while ( a!=0 ) {
...
a= readInt();
}

Se puede apreciar que el primer trozo de código resulta más breve que el
segundo.

10.Define el concepto de parámetro y explique ampliamente como


se utiliza

Parámetros

Los parámetros se usan para mandar valores a la función, con los que
ella trabajará para realizar las acciones. Son los valores de entrada que
recibe una función. Por ejemplo, una función que realizase una suma de
dos números tendría como parámetros a esos dos números. Los dos
números son la entrada, así como la salida sería el resultado, pero eso lo
veremos más tarde.
Veamos un ejemplo anterior en el que creábamos una función para
mostrar un mensaje de bienvenida en la página web, pero al que ahora
le vamos a pasar un parámetro que contendrá el nombre de la persona a
la que hay que saludar.

function escribirBienvenida(nombre){
document.write("<H1>Hola " + nombre + "</H1>")
}

Como podemos ver en el ejemplo, para definir en la función un


parámetro tenemos que poner el nombre de la variable que va a
almacenar el dato que le pasemos. Esa variable, que en este caso se
llama nombre, tendrá como valor el dato que le pasemos a la función
cuando la llamemos, además, la variable tendrá vida durante la
ejecución de la función y dejará de existir cuando la función termine su
ejecución.

Para llamar a una función que tiene parámetros se coloca entre


paréntesis el valor del parámetro. Para llamar a la función del ejemplo
habría que escribir:

escribirBienvenida("Alberto García")

Al llamar a la función así, el parámetro nombre toma como valor "Alberto


García" y al escribir el saludo por pantalla escribirá "Hola Alberto García"
entre etiquetas <H1>.

Los parámetros pueden recibir cualquier tipo de datos, numérico,


textual, boleano o un objeto. Realmente no especificamos el tipo del
parámetro, por eso debemos tener un cuidado especial al definir las
acciones que realizamos dentro de la función y al pasarle valores a la
función para asegurarnos que todo es consecuente con los tipos de
nuestras variables o parámetros.

Múltiples parámetros

Una función puede recibir tantos parámetros como queramos y para


expresarlo se colocan los parámetros separados por comas dentro de los
paréntesis. Veamos rápidamente la sintaxis para que la función de antes
reciba dos parámetros, el primero el nombre al que saludar y el segundo
el color del texto.
function escribirBienvenida(nombre,colorTexto){
document.write("<FONT color=" + colorTexto + ">)
document.write("<H1>Hola " + nombre + "</H1>")
document.write("</FONT>")
}

Llamaríamos a la función con esta sintaxis. Entre los paréntesis


colocaremos los valores de los parámetros.

var miNombre = "Pepe"


var miColor = "red"
escribirBienvenida(miNombre,miColor)

He colocado entre los paréntesis dos variables en lugar de dos textos


entrecomillados. Cuando colocamos variables entre los parámetros en
realidad lo que estamos pasando a la función son los valores que
contienen las variables y no las mismas variables.

Parámetros se pasan por valor

Al hilo del uso de parámetros en nuestros programas Javascript tenemos


que indicar que los parámetros de las funciones se pasan por valor. Esto
quiere decir que aunque modifiquemos un parámetro en una función la
variable original que habíamos pasado no cambiará su valor. Se puede
ver fácilmente con un ejemplo.

function pasoPorValor(miParametro){
miParametro = 32
document.write("he cambiado el valor a 32")
}
var miVariable = 5
pasoPorValor(miVariable)
document.write ("el valor de la variable es: " + miVariable)

En el ejemplo tenemos una función que recibe un parámetro y que


modifica el valor del parámetro asignándole el valor 32. También
tenemos una variable, que inicializamos a 5 y posteriormente llamamos
a la función pasándole esta variable como parámetro. Como dentro de la
función modificamos el valor del parámetro podría pasar que la variable
original cambiase de valor, pero como los parámetros no modifican el
valor original de las variables esta no cambia de valor. De este modo, al
imprimir en pantalla el valor de miVariable se imprimirá el número 5, que
es el valor original de la variable, en lugar de 32 que era el valor col el
que habíamos actualizado el parámetro.
En javascript sólo se pueden pasar las variables por valor.

Un parametro es una variable que puede pasar su valor a un


procedimiento desde el principal o desde otro procedimiento.

Existen ocasiones en que es necesario mandar al procedimiento ciertos


valores para que los use en algún proceso.

Estos valores que se pasan del cuerpo principal del programa al


procedimiento se llaman parametros.

Entonces una declaracion completa es:

Static void NomProc(lista de parametros)

{ cuerpo de instrucciones; };

prog13.java

import java.lang.*;

import java.io.*;

class prog13 {

public static void main(String[] args) {

// llamando procedimiento1 y pasando algunos parametros

double beta=3.1416;

proc1(8+4 , beta, "juan" );

}; // cierra main
public static void proc1(int a, double b, String nom )

double c = a + b;

System.out.println(nom+ " la suma fue =" + c);

}; // cierra proc1

} // cierra clase

REGLAS PARA EL USO DE PARAMETROS

1.- Cuando se usan variables como parametros, la variable que se


manda debe ser declarada dentro del principal o del procedimiento de
donde se esta enviando.

2.- La variable que se manda tiene un nombre, la que se recibe puede


tener otro nombre.

3.- La cantidad de variables que se envian deben ser igual en cantidad,


orden y tipo a las variables que reciben.

4.- La variable que recibe tiene un ambito local dentro del


procedimiento, es decir solo la puede usar ese procedimiento.

Y se pueden mandar datos, valores (excepto decimales), expresiones


algebraicas, pero siempre se recibe en variables.

Se utiliza en la documentación de métodos y permite la documentación


de los parámetros. El formato consiste en indicar un parámetro y en las
líneas siguientes colocar la descripción, que se considera concluida
cuando aparece otro tag de documentación. Se suele colocar un tag
@param por cada parámetro.

Una solución mejor es crear un método que tome las dimensiones del
cubo dentro de sus parámetros y establezca las variables de instancia de
forma apropiada. Este concepto se implementará en el siguiente
ejemplo:

/* Un programa que utiliza un método con parámetros en la clase Cubo */

class Cubo {

double ancho;

double alto;

double largo;

double volumen(){

return(ancho * alto * largo);

void setDim(double x, double y, double z){

ancho = x;

alto = y;

largo = z;

// esta clase declara un objeto de tipo Cubo


class CuboDemo{

public static void main(String args[]){

Cubo micubo = new Cubo();

double vol;

// Inicializa el cubo

micubo.setDim(10,20,15);

// cálculo del volumen de Cubo

vol = micubo.volumen();

System.out.println("Volumen igual a : "+ vol);

System.out.println("Volumen igual a : "+ micubo.volumen());

System.out.println();// estas sentencias son equivalentes.

11.Tomando en cuenta el concepto de parámetro de 5 ejemplos de


programas donde se utilizan los parámetros

#include <stdio.h>

main()
{

int i1,i2;
i1=5; i2=105;

printf(''En main1: valor i1,i2:%d,%dnn'',i1,i2);


proc(i1,&i2);
printf(''En main2: valor i1,i2:%d,%dnn'',i1,i2);
}

proc(p1,p2)
int p1;
int *p2;
{

printf(''Dentro proc1; valor i1,i2:%d,%dnn'',p1,*p2);


*p2 = *p2+p1;
p1 = p1*2;
printf(''Dentro proc2; valor i1,i2:%d,%dnn'',p1,*p2);
printf(''Dentro proce; dar valores i1,i2:'');
scanf(''%d%d'',&p1,&*p2);
printf(''Dentro proc3; valor i1,i2:%d,%dnn'',p1,*p2);
}

12.Define el concepto constructor y explique ampliamente para que


sirve dentro de un programa

Los constructores son funciones, o métodos, que se encargan de realizar


las tareas de inicialización de los objetos al ser instanciados. Es decir,
cuando se crean los objetos a partir de las clases, se llama a un constructor
que se encarga de inicializar los atributos del objeto y realizar cualquier
otra tarea de inicialización que sea necesaria.

No es obligatorio disponer de un constructor, pero resultan muy útiles y su


uso es muy habitual. En el ejemplo de la caja, que comentábamos en el
anterior artículo de programación orientada a objetos en PHP, lo normal
sería inicializar las variables como color o las relacionadas con las
dimensiones y, además, indicar que el contenido de la caja está vacío. Si no
hay un constructor no se inicializan ninguno de los atributos de los objetos.

El constructor se define dentro de la propia clase, como si fuera otro


método. El único detalle es que el constructor debe tener el mismo nombre
que la clase. Atentos a PHP, que diferencia entre mayúsculas y minúsculas.

Para la clase Caja definida anteriormente, se podría declarar este


constructor:

function Caja($alto=1,$ancho=1,$largo=1,$color="negro"){
$this->alto=$alto;
$this->ancho=$ancho;
$this->largo=$largo;
$this->color=$color;
$this->contenido="";
}
En este constructor recibimos por parámetro todos los atributos que hay
que definir en una caja.

Es muy útil definir unos valores por defecto en los parámetros que recibe el
constructor, igualando el parámetro a un valor dentro de la declaración de
parámetros de la función constructora, pues así, aunque se llame al
constructor sin proporcionar parámetros, se inicializará con los valores por
defecto que se hayan definido.

Es importante señalar que en los constructores no se tienen por qué recibir


todos los valores para inicializar el objeto. Hay algunos valores que pueden
inicializarse a vacío o a cualquier otro valor fijo, como en este caso el
contenido de la caja, que inicialmente hemos supuesto que estará vacía.

Un constructor es una función especial que sirve para construir o inicializar


objetos. En C++ la inicialización de objetos no se puede realizar en el
momento en que son declarados; sin embargo, tiene una característica
muy importante y es disponer de una función llamada constructor que
permite inicializar objetos en el momento en que se crean.

Un constructor es una función que sirve para construir un nuevo objeto y


asignar valores a sus miembros dato. Se caracteriza por:
- Tener el mismo nombre de la clase que inicializa
- Puede definirse inline o fuera de la declaración de la clase
- No devuelve valores
- Puede admitir parámetros como cualquier otra función
- Puede existir más de un constructor, e incluso no existir

Si no se define ningún constructor de una clase, el compilador generará un


constructor por defecto. El constructor por defecto no tiene argumentos y
simplemente sitúa ceros en cada byte de las variables instancia de un
objeto. Si se definen constructores para una clase, el constructor por
defecto no se genera.

Un constructor del objeto se llama cuando se crea el objeto implícitamente:


nunca se llama explícitamente a las funciones constructoras. Esto significa
que se llama cuando se ejecuta la declaración del objeto. También, para
objetos locales, el constructor se llama cada vez que la declaración del
objeto se encuentra. En objetos globales, el constructor se llama cuando se
arranca el programa.

El constructor por defecto es un constructor que no acepta argumentos. Se


llama cuando se define una instancia pero no se especifica un valor inicial.

Se pueden declarar en una clase constructores múltiples, mientras tomen


parte diferentes tipos o número de argumentos. El compilador es entonces
capaz de determinar automáticamente a qué constructor llamar en cada
caso, examinando los argumentos.

Los argumentos por defecto se pueden especificar en la declaración del


constructor. Los miembros dato se inicializarán a esos valores por defecto,
si ningún otro se especifica.

C++ ofrece un mecanismo alternativo para pasar valores de parámetros a


miembros dato. Este mecanismo consiste en inicializar miembros dato con
parámetros.

class prueba
{
tipo1 d1;
tipo2 d2;
tipo3 d3;
public:
prueba(tipo1 p1, tipo2 p2, tipo3 p3):d1(p1),d2(p2),d3(p3)
{}
};

Un constructor que crea un nuevo objeto a partir de uno existente se llama


constructor copiador o de copias. El constructor de copias tiene sólo un
argumento: una referencia constante a un objeto de la misma clase. Un
constructor copiador de una clase complejo es:
complejo::complejo(const complejo &fuente)
{
real=fuente.real;imag=fuente.imag;
}

Si no se incluye un constructor de copia, el compilador creará un


constructor de copia por defecto. Este sistema funciona de un modo
perfectamente satisfactorio en la mayoría de los casos, aunque en
ocasiones puede producir dificultades. El constructor de copia por defecto
inicializa cada elemento de datos del objeto a la izquierda del operador = al
valor del elmento dato equivalente del objeto de la derecha del operador =.
Cuando no hay punteros invicados, eso funciona bien. Sin embargo, cuando
se utilizan punteros, el constructor de copia por defecto inicializará el valor
de un elemento puntero de la izquierda del operador = al del elemento
equivalente de la derecha del operador; es decir que los dos punteros
apuntan en la misma dirección. Si ésta no es la situación que se desea, hay
que escribir un constructor de copia.

13.Mediante 5 ejemplos de programación señale y explique el o los


constructores utilizados

class NLog
{
// Private Constructor:
private NLog() { }

public static double e = System.Math.E; //2.71828...


}

public class Counter


{
private Counter() { }
public static int currentCount;
public static int IncrementCount()
{
return ++currentCount;
}
}

class TestCounter
{
static void Main()
{
// If you uncomment the following statement, it will generate
// an error because the constructor is inaccessible:
// Counter aCounter = new Counter(); // Error

Counter.currentCount = 100;
Counter.IncrementCount();
System.Console.WriteLine("New count: {0}", Counter.currentCount);
}
}

Ejemplo:
class Persona
{
public Persona( ) //Constructor personalizado
{
Nombre = "";
Apellido = "";
Console.WriteLine("Objeto Construido");
}
public string ObtenerNombreCompleto()
{
return ( Nombre+" "+Apellido );
}
public string nombre
{
get{ return Nombre; }
set{ Nombre = value ; }
}
public string apellido
{
get{ return Apellido; }
set{ Apellido = value; }
}
private string Nombre,Apellido;
}

Algo importante es que podemos modificar la accesibilidad de un


constructor.

14.Define el concepto de destructor y explique ampliamente para


que sirve dentro de un programa

El destructor es muy similar al constructor, excepto que es llamado


automáticamente cuando cada objeto sale de su ámbito de validez.
Recordemos que las variables automáticas tienen un tiempo de vida
limitado, ya que dejan de existir cuando se sale del bloque en que han sido
declaradas. Cuando un objeto es liberado automáticamente, su destructor, si
existe, es llamado automáticamente.
Un destructor tiene el mismo nombre que la clase a la que pertenece, pero
precedido con una tilde (~). Un destructor no tiene tipo devuelto.
En el ejemplo anterior, podemos definir un destructor que asigne cero a las
variables antes de que sean liberadas, con lo que en realidad no estamos
haciendo nada

Los destructores son un tipo especial de función miembro, estrechamente


relacionados con los constructores. Son también funciones que no devuelven
nada (ni siquiera void). Tampoco aceptan ningún parámetro, ya que la
destrucción de un objeto no acepta ningún tipo de opción o especificación
particular y es idéntica para todos los objetos de la clase. Los destructores
no pueden ser heredados, aunque una clase derivada puede llamar a los
destructores de su superclase si no han sido declarados privados (son
públicos o protegidos). Lo mismo que ocurre con los constructores, tampoco
puede obtenerse su dirección, por lo que no es posible establecer punteros a
este tipo de funciones.

La misión más común de los destructores es liberar la memoria asignada por


los constructores, aunque también puede consistir en desasignar y/o liberar
determinados recursos asignados por estos. Por ejemplo, cerrar un fichero o
desbloquear un recurso compartido previamente bloqueado por el
constructor.

Se ha señalado que, si el programador no define uno explícitamente, el


compilador C++ proporciona un destructor de oficio, que es declarado
público y puede ser invocado sin argumentos. Por lo general en la mayoría
de los casos este destructor de oficio es suficiente, por lo que el
programador no necesita definir uno por sí mismo, a no ser que la clase
incluya la inicialización de objetos persistentes. Por ejemplo, matrices que
necesiten del operador new en el constructor para su inicialización, en cuyo
caso es responsabilidad del programador definir un destructor adecuado.

Los destructores son invocados automáticamente (de forma implícita) por el


programa en multitud de ocasiones; de hecho es muy raro que sea necesario
invocarlos explícitamente. Su misión es limpiar los miembros del objeto
antes que el propio objeto se auto-destruya. Declaración

Los destructores se distinguen porque tienen el mismo nombre que la clase


a que pertenecen precedido por la tilde ~ para simbolizar su estrecha
relación con los constructores que utilizan el mismo nombre (son el
"complemento" de aquellos).

15.Mediante 5 ejemplos de programación señale y explique el o los


destructores utilizados

Ejemplo:

class X {
public:
~X(); // destructor de la clase X
};
...
X::~X() { // definición (off-line) del destructor
...
}
#include <stdlib.h>

class X { // clase
public:
...
~X(){}; // destructor de la clase
};
void* operator new(size_t size, void *ptr) {
return ptr;
}
char buffer[sizeof(X)]; // matriz de caracteres, del tamaño de X

void main() { // ========================


X* ptr1 = new X; // puntero a objeto X creado con new
X* ptr2; // puntero a objeto X
ptr2 = new(&buffer) X; // se inicia con la dirección de buffer
...
delete ptr1; // delete destruye el puntero
ptr2–>X::~X(); // llamada directa, desasignar el espacio de buffer
}

En el siguiente ejemplo se muestra claramente como se invoca el destructor


cuando un objeto sale de ámbito al terminar el bloque en que ha sido
declarado.

#include <iostream>
using namespace std;

class A {
public:
int x;
A(int i = 1) { x = i; } // constructor por defecto
~A() { // destructor
cout << "El destructor ha sido invocado" << endl;
}
};

int main() { // =========================


{
A a; // se instancia un objeto
cout << "Valor de a.x: " << a.x << endl;
} // punto de invocación del destructor de a
return 0;
}

Salida:

Valor de a.x: 1
El destructor ha sido invocado

# include <iostream.h>

class Caja {
double longitud, anchura, altura;
public:
Caja (double dim1, double dim2, double dim3);
~Caja (void);
double volumen (void);
};

Caja :: Caja (double dim1, double dim2, double dim3)


{
longitud = dim1;
anchura = dim2;
altura = dim3;
};

Caja::~Caja (void) { longitud = 0; anchura = 0; altura = 0; } double


Caja:: volumen (void) {
return longitud * anchura * altura;
};

main ()
{
Caja pequeña(5, 4, 10), mediana (10, 6, 20), grande(20, 10, 30);
cout << "El volumen de la caja grande es " << grande.volumen() << '\n';
}

Si algún bloque de memoria fuera reservada dinámicamente en un objeto,


se puede utilizar el destructor para liberarla antes de que se pierdan los
punteros a esas variables.

#include <iostream.h>

class Taco {
public:
Taco (int hard) {
hardness = new int;
*hardness = hard;
}
~Taco() {
cout << "Destroying taco with hardness " ;
cout << *hardness <<;\n';
delete hardness;
}
private:
int *hardness; };

main ()
{
Taco hard(10);
Taco *soft = new Taco (0);

delete soft;
};

En este ejemplo, vemos que el constructor tiene el mismo nombre que la


clase, con un ~ delante. Cuando se crean punteros a clases, como soft en el
ejemplo, se llama al destructor cuando se libera la memoria del puntero. Si
esto no se hace, nunca se llamará al destructor.
Con clases declaradas estáticamente, como Taco hard, el destructor se llama
al final de la función donde se declara el objeto (en el ejemplo, al final de la
función main.
Incluse cuando se interrumpe un programa usando una llamada a exit(), se
llama a los destructores de los objetos que existen en ese momento.

Ejemplo

class X {...}; // X es una clase


...
{
X obj1; // L.4: objeto automático
X* ptr = new(X) // L.5: objeto persistente
X* pt2 = &obj1; // Ok: pt2 es puntero a obj1 de la clase X
...
pt2–>X::~X(); // L.8: Ok: llamada legal del destructor
// pt2->~X(); L.9: Ok: variación sintáctica de la anterior
// obj1.~X(); L.10: Ok otra posibilidad análoga
X::~X(); // L.11: Error: llamada ilegal al destructor [1]
delete ptr; // L.12: Ok. invocación implícita al destructor
}

S-ar putea să vă placă și