Epic Cosmos 1: los objetos en el espacio
En resumen: Un juego con objetos: estrellas, planetas y satélites son clases, la regla de «qué orbita alrededor de qué» es un método compartido, y una órbita no válida lanza tu propia excepción.
Problema
La carrera espacial
La humanidad ya puede volar a planetas lejanos. Empresas y países compiten por sus recursos. Tú diriges una de las misiones y quieres convertirte en la mayor potencia del espacio.
Las reglas de Epic Cosmos:
- Ganas puntos al descubrir nuevos planetas y objetos, extraer recursos, construir edificios y naves, y hacer descubrimientos científicos.
- Los objetos son estrellas, planetas y satélites. Una estrella da energía. Algunos planetas tienen recursos raros, y su atmósfera decide qué se puede construir allí. Un satélite sirve para las comunicaciones y la exploración.
- Necesitas recursos para construir, investigar y mantener en marcha tus bases y naves.
- Los edificios extraen recursos, investigan tecnologías, defienden la base y fabrican naves.
- Las tecnologías desbloquean nuevos edificios, naves y habilidades.
- Conflictos: en el espacio no estás solo. Hay piratas y otros jugadores.
- El final: el juego termina cuando alguien alcanza un número fijo de puntos o después de un número fijo de turnos. Gana el jugador con más puntos.
Antes de los edificios y las naves necesitas el mundo mismo: qué objetos hay, dónde están y qué puede orbitar alrededor de qué. De eso trata esta lección. Los recursos, los edificios y las naves están en la siguiente.
La idea
Todo en el espacio es un SpaceObject
Una estrella, un planeta y un satélite tienen algo en común: un nombre, las coordenadas x, y, z y una masa. Lo común va a una clase abstracta:
abstract class SpaceObject { private String name; private double coordinateX; private double coordinateY; private double coordinateZ; private double mass;
public SpaceObject(String name, double coordinateX, double coordinateY, double coordinateZ, double mass) { this.name = name; this.coordinateX = coordinateX; this.coordinateY = coordinateY; this.coordinateZ = coordinateZ; this.mass = mass; }
public String getName() { return name; }
public double getCoordinateX() { return coordinateX; }
public double getCoordinateY() { return coordinateY; }
public double getCoordinateZ() { return coordinateZ; }
public double getMass() { return mass; }
public abstract String getKind();
public void displayInfo() { System.out.printf("%s %s: (%.1f, %.1f, %.1f), masa %.2f%n", getKind(), name, coordinateX, coordinateY, coordinateZ, mass); }
protected void moveTo(double x, double y, double z) { coordinateX = x; coordinateY = y; coordinateZ = z; }}abstract class SpaceObject{ public string Name { get; } public double CoordinateX { get; private set; } public double CoordinateY { get; private set; } public double CoordinateZ { get; private set; } public double Mass { get; }
public SpaceObject(string name, double coordinateX, double coordinateY, double coordinateZ, double mass) { Name = name; CoordinateX = coordinateX; CoordinateY = coordinateY; CoordinateZ = coordinateZ; Mass = mass; }
public abstract string GetKind();
public void DisplayInfo() { Console.WriteLine($"{GetKind()} {Name}: ({CoordinateX:F1}, {CoordinateY:F1}, {CoordinateZ:F1}), masa {Mass:F2}"); }
protected void MoveTo(double x, double y, double z) { CoordinateX = x; CoordinateY = y; CoordinateZ = z; }}class SpaceObject(ABC): def __init__(self, name, coordinate_x, coordinate_y, coordinate_z, mass): self._name = name self._coordinate_x = coordinate_x self._coordinate_y = coordinate_y self._coordinate_z = coordinate_z self._mass = mass
@property def name(self): return self._name
@property def coordinate_x(self): return self._coordinate_x
@property def coordinate_y(self): return self._coordinate_y
@property def coordinate_z(self): return self._coordinate_z
@property def mass(self): return self._mass
@abstractmethod def get_kind(self): pass
def display_info(self): print(f"{self.get_kind()} {self._name}: ({self._coordinate_x:.1f}, {self._coordinate_y:.1f}, {self._coordinate_z:.1f}), masa {self._mass:.2f}")
def _move_to(self, x, y, z): self._coordinate_x = x self._coordinate_y = y self._coordinate_z = zclass SpaceObject { #name; #coordinateX; #coordinateY; #coordinateZ; #mass;
constructor(name, coordinateX, coordinateY, coordinateZ, mass) { this.#name = name; this.#coordinateX = coordinateX; this.#coordinateY = coordinateY; this.#coordinateZ = coordinateZ; this.#mass = mass; }
get name() { return this.#name; }
get coordinateX() { return this.#coordinateX; }
get coordinateY() { return this.#coordinateY; }
get coordinateZ() { return this.#coordinateZ; }
get mass() { return this.#mass; }
getKind() { throw new Error(`${this.constructor.name} debe escribir getKind()`); }
displayInfo() { console.log(`${this.getKind()} ${this.#name}: (${this.#coordinateX.toFixed(1)}, ${this.#coordinateY.toFixed(1)}, ${this.#coordinateZ.toFixed(1)}), masa ${this.#mass.toFixed(2)}`); }
_moveTo(x, y, z) { this.#coordinateX = x; this.#coordinateY = y; this.#coordinateZ = z; }}- Las coordenadas están en millones de kilómetros desde el Sol, y la masa está en masas terrestres: la Tierra es 1, el Sol es 333 000.
displayInfo()es común a todos. El tipo (getKind()) es abstracto: cada subclase dice por sí misma qué es.-
#namey los demás campos con#están realmente ocultos: no puedes llegar a ellos desde fuera, por eso los lees medianteget name(). Pero#tampoco se ve en las subclases, y JavaScript no tieneprotected. Por eso_moveTolleva un guion bajo: una convención para «solo para subclases» que JavaScript no impone.
JavaScript no tiene clases ni métodos abstractos. Lo más cercano es que getKind() en el padre lance un error: una subclase que no lo escribe se entera en la primera llamada. Un objeto de esa clase se crea sin ningún problema:
class Comet extends SpaceObject {}
const comet = new Comet("Halley", 0, 0, 0, 0);try { comet.displayInfo();} catch (e) { console.log(e.message);}Comet debe escribir getKind()La estrella es la subclase más simple:
class Star extends OrbitableSpaceObject { public Star(String name, double coordinateX, double coordinateY, double coordinateZ, double mass) { super(name, coordinateX, coordinateY, coordinateZ, mass); }
@Override public String getKind() { return "Estrella"; }}class Star : OrbitableSpaceObject{ public Star(string name, double coordinateX, double coordinateY, double coordinateZ, double mass) : base(name, coordinateX, coordinateY, coordinateZ, mass) { }
public override string GetKind() { return "Estrella"; }}class Star(OrbitableSpaceObject): def get_kind(self): return "Estrella"class Star extends OrbitableSpaceObject { getKind() { return "Estrella"; }}El constructor se hereda: new Star(...) llama al constructor del padre con los mismos argumentos. Por eso Star solo escribe su tipo.
Los tres tipos de objetos van en un array de SpaceObject. El bucle no sabe cuál es cuál, y cada uno dice su propio tipo:
SpaceObject[] objects = { new Star("Sol", 0, 0, 0, 333000), new Planet("Tierra", 149.6, 0, 0, 1), new Satellite("Luna", 150, 0, 0, 0.012),};for (SpaceObject object : objects) { object.displayInfo();}Estrella Sol: (0.0, 0.0, 0.0), masa 333000.00Planeta Tierra: (149.6, 0.0, 0.0), masa 1.00Satélite Luna: (150.0, 0.0, 0.0), masa 0.01SpaceObject[] objects ={ new Star("Sol", 0, 0, 0, 333000), new Planet("Tierra", 149.6, 0, 0, 1), new Satellite("Luna", 150, 0, 0, 0.012),};foreach (SpaceObject spaceObject in objects){ spaceObject.DisplayInfo();}Estrella Sol: (0.0, 0.0, 0.0), masa 333000.00Planeta Tierra: (149.6, 0.0, 0.0), masa 1.00Satélite Luna: (150.0, 0.0, 0.0), masa 0.01objects = [ Star("Sol", 0, 0, 0, 333000), Planet("Tierra", 149.6, 0, 0, 1), Satellite("Luna", 150, 0, 0, 0.012),]for space_object in objects: space_object.display_info()Estrella Sol: (0.0, 0.0, 0.0), masa 333000.00Planeta Tierra: (149.6, 0.0, 0.0), masa 1.00Satélite Luna: (150.0, 0.0, 0.0), masa 0.01const objects = [ new Star("Sol", 0, 0, 0, 333000), new Planet("Tierra", 149.6, 0, 0, 1), new Satellite("Luna", 150, 0, 0, 0.012),];for (const spaceObject of objects) { spaceObject.displayInfo();}Estrella Sol: (0.0, 0.0, 0.0), masa 333000.00Planeta Tierra: (149.6, 0.0, 0.0), masa 1.00Satélite Luna: (150.0, 0.0, 0.0), masa 0.01La idea
Objetos alrededor de los que se orbita
Los planetas orbitan alrededor de una estrella, y los satélites orbitan alrededor de un planeta. Tanto la estrella como el planeta tienen que recordar qué orbita a su alrededor. Eso es OrbitableSpaceObject: una clase abstracta entre SpaceObject y ellos.
abstract class OrbitableSpaceObject extends SpaceObject { private SpaceObject[] orbiters = new SpaceObject[10]; private int orbiterCount = 0;
public OrbitableSpaceObject(String name, double coordinateX, double coordinateY, double coordinateZ, double mass) { super(name, coordinateX, coordinateY, coordinateZ, mass); }
public void addOrbiter(SpaceObject orbiter) { if (orbiterCount == orbiters.length) { throw new IllegalStateException("Alrededor de " + getName() + " ya orbitan " + orbiters.length + " objetos"); } orbiters[orbiterCount] = orbiter; orbiterCount++; }
public SpaceObject[] getOrbiters() { SpaceObject[] result = new SpaceObject[orbiterCount]; for (int i = 0; i < orbiterCount; i++) { result[i] = orbiters[i]; } return result; }}abstract class OrbitableSpaceObject : SpaceObject{ private SpaceObject[] orbiters = new SpaceObject[10]; private int orbiterCount = 0;
public OrbitableSpaceObject(string name, double coordinateX, double coordinateY, double coordinateZ, double mass) : base(name, coordinateX, coordinateY, coordinateZ, mass) { }
public void AddOrbiter(SpaceObject orbiter) { if (orbiterCount == orbiters.Length) { throw new InvalidOperationException("Alrededor de " + Name + " ya orbitan " + orbiters.Length + " objetos"); } orbiters[orbiterCount] = orbiter; orbiterCount++; }
public SpaceObject[] GetOrbiters() { SpaceObject[] result = new SpaceObject[orbiterCount]; for (int i = 0; i < orbiterCount; i++) { result[i] = orbiters[i]; } return result; }}class OrbitableSpaceObject(SpaceObject): CAPACITY = 10
def __init__(self, name, coordinate_x, coordinate_y, coordinate_z, mass): super().__init__(name, coordinate_x, coordinate_y, coordinate_z, mass) self._orbiters = []
def add_orbiter(self, orbiter): if len(self._orbiters) == self.CAPACITY: raise RuntimeError(f"Alrededor de {self.name} ya orbitan {self.CAPACITY} objetos") self._orbiters.append(orbiter)
def get_orbiters(self): return list(self._orbiters)class OrbitableSpaceObject extends SpaceObject { static CAPACITY = 10; #orbiters = [];
addOrbiter(orbiter) { if (this.#orbiters.length === OrbitableSpaceObject.CAPACITY) { throw new Error(`Alrededor de ${this.name} ya orbitan ${OrbitableSpaceObject.CAPACITY} objetos`); } this.#orbiters.push(orbiter); }
getOrbiters() { return [...this.#orbiters]; }}- Los objetos que orbitan están en un array que crece sola. No necesitas un contador:
this.#orbiters.lengthdice cuántos hay. - Una estrella tiene lugar para 10 objetos:
CAPACITYestá en la clase, compartida por todos sus objetos. Si el lugar se llena,addOrbiterlanza unErrorsimple: JavaScript no tiene una excepción aparte para el momento equivocado. getOrbiters()devuelve una copia de el array.
Más precisamente, para curiosos
getOrbiters()devuelve una copia, no el array mismo. Si no, el código de fuera podría añadir conpushy saltarse la comprobación de lugar.StarextiendeOrbitableSpaceObject, noSpaceObjectdirectamente. Así la estrella recibe tanto los objetos que orbitan como todo lo deSpaceObject.
La copia se ve en la salida: lo que añades a ella no llega a la estrella.
const sun = new Star("Sol", 0, 0, 0, 333000);new Planet("Tierra", 149.6, 0, 0, 1).orbit(sun);const copy = sun.getOrbiters();copy.push(new Planet("Marte", 227.9, 0, 0, 0.11));console.log(copy.length, sun.getOrbiters().length);Tierra orbita alrededor de Sol2 1La idea
La regla de las órbitas
Un planeta orbita alrededor de una estrella. Un satélite orbita alrededor de un planeta. Todo lo demás no es válido. Los objetos que pueden orbitar comparten un contrato:
interface Orbiter { void orbit(SpaceObject target) throws NotValidSpaceObjectException;}interface Orbiter{ void Orbit(SpaceObject target);}class Orbiter(ABC): @abstractmethod def orbit(self, target): pass// El contrato Orbiter: el objeto tiene un método orbit(target) que lo hace orbitar// alrededor de target o lanza NotValidSpaceObjectError.// JavaScript no tiene interface: Planet y Satellite simplemente tienen ese método.JavaScript no tiene interfaces. El contrato es un acuerdo: todo objeto que puede orbitar tiene un método orbit(target). El código que lo usa simplemente lo llama, sin preguntar qué es el objeto. Esto se llama duck typing: «si camina como un pato y grazna como un pato, es un pato».
Si se rompe la regla, orbit lanza una excepción propia. El nombre dice exactamente qué pasó:
class NotValidSpaceObjectException extends Exception { public NotValidSpaceObjectException(String message) { super(message); }}class NotValidSpaceObjectException : Exception{ public NotValidSpaceObjectException(string message) : base(message) { }}class NotValidSpaceObjectError(Exception): passclass NotValidSpaceObjectError extends Error { constructor(message) { super(message); this.name = "NotValidSpaceObjectError"; }}Así hace cumplir la regla el planeta:
@Overridepublic void orbit(SpaceObject target) throws NotValidSpaceObjectException { if (target instanceof Star star) { star.addOrbiter(this); System.out.println(getName() + " orbita alrededor de " + star.getName()); } else { throw new NotValidSpaceObjectException(getName() + " no puede orbitar alrededor de " + target.getName() + ": un planeta orbita solo una estrella"); }}public void Orbit(SpaceObject target){ if (target is Star star) { star.AddOrbiter(this); Console.WriteLine(Name + " orbita alrededor de " + star.Name); } else { throw new NotValidSpaceObjectException(Name + " no puede orbitar alrededor de " + target.Name + ": un planeta orbita solo una estrella"); }}def orbit(self, target): if isinstance(target, Star): target.add_orbiter(self) print(f"{self.name} orbita alrededor de {target.name}") else: raise NotValidSpaceObjectError(f"{self.name} no puede orbitar alrededor de {target.name}: un planeta orbita solo una estrella")orbit(target) { if (target instanceof Star) { target.addOrbiter(this); console.log(`${this.name} orbita alrededor de ${target.name}`); } else { throw new NotValidSpaceObjectError(`${this.name} no puede orbitar alrededor de ${target.name}: un planeta orbita solo una estrella`); }}target instanceof Starcomprueba el tipo. Después de la comprobación usastargetcomo estrella: no necesitas una variable nueva.- Si la comprobación falla, la excepción detiene el método. El planeta no se añade a ningún lado.
Satellitetiene el mismoorbit, solo que compruebaPlanet.
Más precisamente, para curiosos
En JavaScript nadie sigue qué lanza qué. Ni el contrato ni orbit dicen que puede lanzar una excepción, y nada obliga a quien llama a capturarla. El programa se detendrá si nadie la captura, así que en el juego siempre la capturamos. El nombre de la excepción termina en Error, como las integradas (TypeError).
Míralo
Qué orbita alrededor de qué
const sun = new Star("Sol", 0, 0, 0, 333000);const earth = new Planet("Tierra", 149.6, 0, 0, 1);const moon = new Satellite("Luna", 150, 0, 0, 0.012);tryOrbit(earth, sun);tryOrbit(moon, earth);tryOrbit(moon, sun);Paso a paso, en palabras
- Tres objetos: una estrella, un planeta y un satélite, cada uno con sus coordenadas y su masa.
- Un planeta alrededor de una estrella: la regla lo permite, y la Tierra se pone en órbita.
- Un satélite alrededor de un planeta: permitido. La Luna orbita alrededor de la Tierra y se mueve con ella.
- Un satélite alrededor de una estrella: orbit lanza NotValidSpaceObjectError, y el catch de tryOrbit imprime el motivo.
La Tierra pasa la comprobación de la estrella y se añade a los objetos que orbitan a su alrededor. La Luna pasa la comprobación de la Tierra. Cuando la Luna intenta orbitar alrededor del Sol, la comprobación de Planet falla. orbit lanza la excepción, y la Luna sigue alrededor de la Tierra.
La excepción se captura en una pequeña función auxiliar. Esta prueba la órbita y, si la rechazan, dice por qué:
static void tryOrbit(Orbiter orbiter, SpaceObject target) { try { orbiter.orbit(target); } catch (NotValidSpaceObjectException e) { System.out.println("Rechazado: " + e.getMessage()); }}static void TryOrbit(Orbiter orbiter, SpaceObject target){ try { orbiter.Orbit(target); } catch (NotValidSpaceObjectException e) { Console.WriteLine("Rechazado: " + e.Message); }}def try_orbit(orbiter, target): try: orbiter.orbit(target) except NotValidSpaceObjectError as e: print(f"Rechazado: {e}")function tryOrbit(orbiter, target) { try { orbiter.orbit(target); } catch (e) { if (!(e instanceof NotValidSpaceObjectError)) { throw e; } console.log(`Rechazado: ${e.message}`); }}catch en JavaScript no tiene un tipo entre paréntesis: captura todos los errores, incluso uno que viene de una errata en el código. Por eso tryOrbit comprueba con instanceof. Imprime una órbita rechazada y relanza cualquier otro error con throw e.
Pruébalo
¿Cuántos orbitan?
Marte intenta orbitar alrededor de la Tierra.
¿Qué imprimirá el programa?
function tryOrbit(orbiter, target) { try { orbiter.orbit(target); } catch (e) { if (!(e instanceof NotValidSpaceObjectError)) { throw e; } console.log(`Rechazado: ${e.message}`); }}
const sun = new Star("Sol", 0, 0, 0, 333000);const earth = new Planet("Tierra", 149.6, 0, 0, 1);const mars = new Planet("Marte", 227.9, 0, 0, 0.11);const moon = new Satellite("Luna", 150, 0, 0, 0.012);tryOrbit(earth, sun);tryOrbit(mars, earth);tryOrbit(moon, earth);console.log(`Alrededor de Sol: ${sun.getOrbiters().length}`);console.log(`Alrededor de Tierra: ${earth.getOrbiters().length}`);Marte no pasa la comprobación de Star y no se añade a ningún lado. La función auxiliar captura el rechazo, así que el programa sigue con la Luna. Solo la Tierra orbita alrededor del Sol, y solo la Luna orbita alrededor de la Tierra.
La idea
Una nave que vuela
Las naves no orbitan. Vuelan de un objeto a otro. Eso es un contrato distinto:
interface Fly { void flyTo(SpaceObject destination) throws NotValidSpaceObjectException;}interface Fly{ void FlyTo(SpaceObject destination);}class Fly(ABC): @abstractmethod def fly_to(self, destination): pass// El contrato Fly: el objeto tiene un método flyTo(destination) que lo mueve hasta destination// o lanza NotValidSpaceObjectError.SpaceShip extiende SpaceObject y tiene un método flyTo. No puede volar a una estrella. Vuela a cualquier otra cosa y toma las coordenadas del destino:
@Overridepublic void flyTo(SpaceObject destination) throws NotValidSpaceObjectException { if (destination instanceof Star) { throw new NotValidSpaceObjectException(getName() + " no puede volar a " + destination.getName() + ": la estrella la quemaría"); } moveTo(destination.getCoordinateX(), destination.getCoordinateY(), destination.getCoordinateZ()); System.out.println(getName() + " llegó a " + destination.getName());}public void FlyTo(SpaceObject destination){ if (destination is Star) { throw new NotValidSpaceObjectException(Name + " no puede volar a " + destination.Name + ": la estrella la quemaría"); } MoveTo(destination.CoordinateX, destination.CoordinateY, destination.CoordinateZ); Console.WriteLine(Name + " llegó a " + destination.Name);}def fly_to(self, destination): if isinstance(destination, Star): raise NotValidSpaceObjectError(f"{self.name} no puede volar a {destination.name}: la estrella la quemaría") self._move_to(destination.coordinate_x, destination.coordinate_y, destination.coordinate_z) print(f"{self.name} llegó a {destination.name}")flyTo(destination) { if (destination instanceof Star) { throw new NotValidSpaceObjectError(`${this.name} no puede volar a ${destination.name}: la estrella la quemaría`); } this._moveTo(destination.coordinateX, destination.coordinateY, destination.coordinateZ); console.log(`${this.name} llegó a ${destination.name}`);}SpaceShip ship = new SpaceShip("Errante", 149.6, 0, 0, 0);Planet mars = new Planet("Marte", 227.9, 0, 0, 0.11);Star sun = new Star("Sol", 0, 0, 0, 333000);try { ship.flyTo(mars); ship.displayInfo(); ship.flyTo(sun); ship.displayInfo();} catch (NotValidSpaceObjectException e) { System.out.println("Rechazado: " + e.getMessage());}Errante llegó a MarteNave Errante: (227.9, 0.0, 0.0), masa 0.00Rechazado: Errante no puede volar a Sol: la estrella la quemaríaSpaceShip ship = new SpaceShip("Errante", 149.6, 0, 0, 0);Planet mars = new Planet("Marte", 227.9, 0, 0, 0.11);Star sun = new Star("Sol", 0, 0, 0, 333000);try{ ship.FlyTo(mars); ship.DisplayInfo(); ship.FlyTo(sun); ship.DisplayInfo();}catch (NotValidSpaceObjectException e){ Console.WriteLine("Rechazado: " + e.Message);}Errante llegó a MarteNave Errante: (227.9, 0.0, 0.0), masa 0.00Rechazado: Errante no puede volar a Sol: la estrella la quemaríaship = SpaceShip("Errante", 149.6, 0, 0, 0)mars = Planet("Marte", 227.9, 0, 0, 0.11)sun = Star("Sol", 0, 0, 0, 333000)try: ship.fly_to(mars) ship.display_info() ship.fly_to(sun) ship.display_info()except NotValidSpaceObjectError as e: print(f"Rechazado: {e}")Errante llegó a MarteNave Errante: (227.9, 0.0, 0.0), masa 0.00Rechazado: Errante no puede volar a Sol: la estrella la quemaríaconst ship = new SpaceShip("Errante", 149.6, 0, 0, 0);const mars = new Planet("Marte", 227.9, 0, 0, 0.11);const sun = new Star("Sol", 0, 0, 0, 333000);try { ship.flyTo(mars); ship.displayInfo(); ship.flyTo(sun); ship.displayInfo();} catch (e) { if (!(e instanceof NotValidSpaceObjectError)) { throw e; } console.log(`Rechazado: ${e.message}`);}Errante llegó a MarteNave Errante: (227.9, 0.0, 0.0), masa 0.00Rechazado: Errante no puede volar a Sol: la estrella la quemaríaEl segundo displayInfo() no se ejecuta: la excepción salta al catch.
Más precisamente, para curiosos
extends toma un solo padre. Un satélite explorador que también pueda volar es class Probe extends SpaceObject con los dos métodos, orbit y flyTo: para el duck typing eso basta.Pruébalo
Encuentra el error
La Luna orbita alrededor del Sol, y no debería. ¿En qué línea del orbit del satélite está el error?
Elige la línea con el error.
OrbitableSpaceObject es el padre tanto de Planet como de Star. La comprobación deja pasar a los dos. Debería ser target instanceof Planet: un satélite orbita solo alrededor de un planeta.
Ejercicio
El espacio en código
Resuelve las tareas en tu editor, con las clases de la lección.
1. El sistema solar. Describe los ocho planetas con tres arrays: nombres, distancias al Sol (millones de km) y masas (masas terrestres). En un bucle, crea cada planeta con x = su distancia y haz que orbite alrededor del Sol. Después muestra todos los objetos que orbitan a su alrededor.
| Planeta | Distancia | Masa |
|---|---|---|
| Mercurio | 57,9 | 0,06 |
| Venus | 108,2 | 0,82 |
| Tierra | 149,6 | 1 |
| Marte | 227,9 | 0,11 |
| Júpiter | 778,5 | 317,8 |
| Saturno | 1432 | 95,2 |
| Urano | 2867 | 14,5 |
| Neptuno | 4515 | 17,1 |
Mercurio orbita alrededor de SolVenus orbita alrededor de SolTierra orbita alrededor de SolMarte orbita alrededor de SolJúpiter orbita alrededor de SolSaturno orbita alrededor de SolUrano orbita alrededor de SolNeptuno orbita alrededor de SolAlrededor de Sol orbitan 8 planetas:Planeta Mercurio: (57.9, 0.0, 0.0), masa 0.06Planeta Venus: (108.2, 0.0, 0.0), masa 0.82Planeta Tierra: (149.6, 0.0, 0.0), masa 1.00Planeta Marte: (227.9, 0.0, 0.0), masa 0.11Planeta Júpiter: (778.5, 0.0, 0.0), masa 317.80Planeta Saturno: (1432.0, 0.0, 0.0), masa 95.20Planeta Urano: (2867.0, 0.0, 0.0), masa 14.50Planeta Neptuno: (4515.0, 0.0, 0.0), masa 17.102. Distancia. Escribe function distance(a, b) con el teorema de Pitágoras en tres dimensiones: la raíz cuadrada de la suma de los cuadrados de las diferencias en x, y y z. La Tierra está en (149,6; 0; 0), Marte está en (0; 227,9; 0), la Luna está en (149,6; 0,4; 0) y el Sol está en el origen.
Tierra – Marte: 272.6 millones de kmTierra – Luna: 0.4 millones de kmSol – Marte: 227.9 millones de km3. El árbol completo. Cambia displayInfo para que la estrella muestre también sus planetas y cada planeta muestre sus satélites, con una sangría de dos espacios por nivel. Pista: un parámetro para la sangría con un valor por defecto, indent = "", para que la llamada también funcione sin argumento. OrbitableSpaceObject sobrescribe el método y llama al del padre. La Tierra y Marte orbitan alrededor del Sol, la Luna orbita alrededor de la Tierra y Fobos orbita alrededor de Marte.
Tierra orbita alrededor de SolMarte orbita alrededor de SolLuna orbita alrededor de TierraFobos orbita alrededor de MarteEstrella Sol: (0.0, 0.0, 0.0), masa 333000.00 Planeta Tierra: (149.6, 0.0, 0.0), masa 1.00 Satélite Luna: (150.0, 0.0, 0.0), masa 0.01 Planeta Marte: (227.9, 0.0, 0.0), masa 0.11 Satélite Fobos: (227.9, 0.0, 0.0), masa 0.00Más tareas
- Añadida dos veces. Ahora mismo la Tierra se puede añadir dos veces a los objetos que orbitan alrededor del Sol. Haz que un segundo intento lance
NotValidSpaceObjectError. - Una estrella llena. Añade 11 planetas a una estrella y captura la excepción en el undécimo.
- Una sonda. Haz una
Probeque orbite y también vuele (mira «Más precisamente, para curiosos» en la parte de las naves).
Test
Ponte a prueba
Lecciones relacionadas
Sección «Lecciones relacionadas»- Se basa en: Interfaces sin interface · Comprobaciones de tipo · Excepciones · Lanzar excepciones y crear las tuyas
- Ejercicios sobre el tema: Hagamos un juego