Ejemplos instanceof

	ArrayList<Animal> zoo = new ArrayList<>();

		Animal mosca = new Insecto();
		Perro firulai = new Perro();
		Insecto libelula = new Insecto();
		firulai.setRaza("Bulldog");
		zoo.add(libelula);
		zoo.add(mosca);
		zoo.add(firulai);

		for (Animal animal : zoo) {
			animal.hacerRuido();
			System.out.println(animal instanceof Perro);
			if (animal instanceof Perro) {
				((Perro) animal).getRaza();
				Perro temp = (Perro) animal;
				System.out.println(temp.getRaza());
			}

		}
	ArrayList<IVolar> elementos = new ArrayList<>();
		Pelicano p = new Pelicano("Pepe");
		Murcielago m = new Murcielago();
		Avion a = new Avion();
		// Añadir a la lista cualquier clase que implemente IVolar
		elementos.add(a);
		elementos.add(p);
		elementos.add(m);

		// Recorrer la lista con un elemento de tipo IVolar
		for (IVolar elemento : elementos) {
			elemento.volar();
		}

		// Lista de elementos que implementan INadar
		ArrayList<INadar> nadadores = new ArrayList<>();
		Delfin f = new Delfin();
		nadadores.add(f);
		nadadores.add(p);
		
		// Instanceof funciona para los Interfaces
		System.out.println(f instanceof INadar); // True
		System.out.println(p instanceof IVolar); // True
		// Recorrer la lista con un elemento de tipo INadar
	
		// Aquí hago un ArrayList de Object
		ArrayList<Object> foo = new ArrayList<>();
		// Puedo añadir cualquier objeto de java
		foo.add(f);
		foo.add(a);
		foo.add(p);
		foo.add(m);
		
		ArrayList<IVolar> vuelan = new ArrayList<>();
		ArrayList<INadar> nadan = new ArrayList<>();
		for(Object o:foo) {
			if (o instanceof IVolar) {
				vuelan.add((IVolar) o);
			}
			if (o instanceof INadar) {
				nadan.add((INadar) o);
			}
		}
		System.out.println(vuelan);
		System.out.println(nadan);

Ejemplo clase final

package com.trifulcas.herencia;

public final class Aviso {
	private String mensaje;

	public Aviso(String mensaje) {
		super();
		this.mensaje = mensaje;
	}
	public void alarma() {
		System.out.println(mensaje);
	}
}

Al ser final, no se puede derivar clases de aquí. Lo siguiente no está permitido:

package com.trifulcas.herencia;

public class AvisoSubClase extends Aviso {

	public AvisoSubClase(String mensaje) {
		super(mensaje);
	}
	@Override
	public void alarma() {
		System.out.println("Mensaje desde una subclase");
	}
}

Lo podemos hacer a nivel de método:

package com.trifulcas.herencia;

public  class Aviso {
	private String mensaje;

	public Aviso(String mensaje) {
		super();
		this.mensaje = mensaje;
	}
	public final void alarma() {
		System.out.println(mensaje);
	}
}

Ahora solo se queja en el método, no en la clase:

package com.trifulcas.herencia;

public class AvisoSubClase extends Aviso {

	public AvisoSubClase(String mensaje) {
		super(mensaje);
	}
	@Override
	public void alarma() {
		System.out.println("Mensaje desde una subclase");
	}
}

Soluciones ejercicios interfaces y abstractas

package com.trifulcas.herencia.ejercicio;

public abstract class Vehiculo {
	private String marca;
	private String modelo;
	private int anyo;
	public Vehiculo(String marca, String modelo, int anyo) {
		super();
		this.marca = marca;
		this.modelo = modelo;
		this.anyo = anyo;
	}
	
	
	/**
	 * @return the marca
	 * 
	 */
	protected String getMarca() {
		return marca;
	}


	


	/**
	 * @return the modelo
	 */
	public String getModelo() {
		return modelo;
	}


	/**
	 * @param modelo the modelo to set
	 */
	public void setModelo(String modelo) {
		this.modelo = modelo;
	}


	/**
	 * @return the anyo
	 */
	public int getAnyo() {
		return anyo;
	}


	/**
	 * @param anyo the anyo to set
	 */
	public void setAnyo(int anyo) {
		this.anyo = anyo;
	}


	public abstract void mostrarDetalles();
	
	public void encender() {
		System.out.println("Vehículo encendido");
	}
}

package com.trifulcas.herencia.ejercicio;

public class Coche extends Vehiculo {

	private int numeroDePuertas;
	public Coche(String marca, String modelo, int anyo, int numeroDePuertas) {
		super(marca, modelo, anyo);
		this.numeroDePuertas=numeroDePuertas;
	}
	
	/**
	 * @return the numeroDePuertas
	 */
	public int getNumeroDePuertas() {
		return numeroDePuertas;
	}

	/**
	 * @param numeroDePuertas the numeroDePuertas to set
	 */
	public void setNumeroDePuertas(int numeroDePuertas) {
		this.numeroDePuertas = numeroDePuertas;
	}

	@Override
	public void mostrarDetalles() {
		System.out.println( getMarca()+" - "+getModelo()+" - "+getAnyo()+" - "+getNumeroDePuertas());
	}

}

package com.trifulcas.herencia.ejercicio;

public class Motocicleta extends Vehiculo {

	public Motocicleta(String marca, String modelo, int anyo, boolean tieneSidecar) {
		super(marca, modelo, anyo);
		this.tieneSidecar=tieneSidecar;
	}

	private boolean tieneSidecar;
	
	/**
	 * @return the tieneSidecar
	 */
	public boolean getTieneSidecar() {
		return tieneSidecar;
	}

	/**
	 * @param tieneSidecar the tieneSidecar to set
	 */
	public void setTieneSidecar(boolean tieneSidecar) {
		this.tieneSidecar = tieneSidecar;
	}

	@Override
	public void mostrarDetalles() {
		System.out.println( getMarca()+" - "+getModelo()+" - "+getAnyo()+" - "+getTieneSidecar());
	}

}

package com.trifulcas.herencia.ejercicio;

public abstract class Empleado {
	private String nombre;
	private int edad;
	private double salario;
	public Empleado(String nombre, int edad, double salario) {
		super();
		this.nombre = nombre;
		this.edad = edad;
		this.salario = salario;
	}
	/**
	 * @return the nombre
	 */
	public String getNombre() {
		return nombre;
	}
	/**
	 * @param nombre the nombre to set
	 */
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}
	/**
	 * @return the edad
	 */
	public int getEdad() {
		return edad;
	}
	/**
	 * @param edad the edad to set
	 */
	public void setEdad(int edad) {
		this.edad = edad;
	}
	/**
	 * @return the salario
	 */
	public double getSalario() {
		return salario;
	}
	/**
	 * @param salario the salario to set
	 */
	public void setSalario(double salario) {
		this.salario = salario;
	}
	
	public abstract double calcularBonificacion();
	
	public void mostrarDetalles() {
		System.out.println(getNombre()+" - "+getEdad()+" - "+getSalario());
	}

}

package com.trifulcas.herencia.ejercicio;

public class EmpleadoMedioTiempo extends Empleado {

	private int horasTrabajadas;

	public EmpleadoMedioTiempo(String nombre, int edad, double salario, int horasTrabajadas) {
		super(nombre, edad, salario);
		this.horasTrabajadas = horasTrabajadas;
	}

	/**
	 * @return the horasTrabajadas
	 */
	public int getHorasTrabajadas() {
		return horasTrabajadas;
	}

	/**
	 * @param horasTrabajadas the horasTrabajadas to set
	 */
	public void setHorasTrabajadas(int horasTrabajadas) {
		this.horasTrabajadas = horasTrabajadas;
	}

	@Override
	public double calcularBonificacion() {
		return getHorasTrabajadas() * 1.2;
	}

	public void mostrarDetalles() {
		System.out.println(getNombre() + " - " + getEdad() + " - " + getSalario() + " - " + getHorasTrabajadas());
	}
}

package com.trifulcas.herencia.ejercicio;

public class EmpleadoTiempoCompleto extends Empleado {


	private double bono;
	
	public EmpleadoTiempoCompleto(String nombre, int edad, double salario, double bono) {
		super(nombre, edad, salario);
		this.bono=bono;
	}

	
	/**
	 * @return the bono
	 */
	public double getBono() {
		return bono;
	}


	/**
	 * @param bono the bono to set
	 */
	public void setBono(double bono) {
		this.bono = bono;
	}


	@Override
	public double calcularBonificacion() {
		return bono;

	}
	@Override
	public void mostrarDetalles() {
		System.out.println(getNombre()+" - "+getEdad()+" - "+getSalario()+" - "+getBono());
	}
}

package com.trifulcas.herencia.ejercicio;

public interface MetodoPago {
	void procesarPago(double monto);
	void mostrarDetalles();
}

package com.trifulcas.herencia.ejercicio;

public class TarjetaCredito implements MetodoPago {

	private String numeroTarjeta;
	private String titular;
	private String fechaExpiracion;
	
	
	public TarjetaCredito(String numeroTarjeta, String titular, String fechaExpiracion) {
		super();
		this.numeroTarjeta = numeroTarjeta;
		this.titular = titular;
		this.fechaExpiracion = fechaExpiracion;
	}

	@Override
	public void procesarPago(double monto) {
		System.out.println("Procesando el pago de "+monto);

	}

	@Override
	public void mostrarDetalles() {
		System.out.println(numeroTarjeta+" - "+titular+" - "+fechaExpiracion);
	}

}

package com.trifulcas.herencia.ejercicio;

public class Paypal implements MetodoPago {

	private String email;
	
	
	public Paypal(String email) {
		super();
		this.email = email;
	}

	@Override
	public void procesarPago(double monto) {
		System.out.println("Procesando el pago PAYPAL de "+monto);


	}

	@Override
	public void mostrarDetalles() {
		System.out.println(email);

	}

}

package com.trifulcas.herencia.ejercicio;

public class TransferenciaBancaria implements MetodoPago {

	private String numeroCuenta;
	private String banco;

	@Override
	public void procesarPago(double monto) {
		System.out.println("Procesando pago Transferencia "+monto);
	}

	@Override
	public void mostrarDetalles() {
		System.out.println(numeroCuenta+" - "+banco);
	}

}

Clase abstracta e interfaces todo junto

package com.trifulcas.herencia.interfaces;

public abstract class Animal {
	private String nombre;

	public Animal(String nombre) {
		super();
		this.nombre = nombre;
	}

	/**
	 * @return the nombre
	 */
	public String getNombre() {
		return nombre;
	}

	/**
	 * @param nombre the nombre to set
	 */
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	@Override
	public String toString() {
		return "Animal [nombre=" + nombre + "]";
	}
	
	public abstract void hacerRuido();
	
}

package com.trifulcas.herencia.interfaces;

public class Pato extends Animal implements IVolar, INadar, ICorrer {

	public Pato(String nombre) {
		super(nombre);
		// TODO Auto-generated constructor stub
	}

	// Lo implemento porque implemento el interfaz IVolar
	@Override
	public void volar() {
		System.out.println("Un patito volando");

	}

	// Lo implemento porque implemento el interfaz ICorrer

	@Override
	public void correr() {
		System.out.println("Un patito corriendo");

	}

	// Lo implemento porque implemento el interfaz INadar

	@Override
	public void nadar() {
		System.out.println("Un patito nadando");

	}

	// Lo tengo que implementar porque lo tiene la clase madre
	// Animal
	@Override
	public void hacerRuido() {
		System.out.println("Cua cua");
		
	}

}

package com.trifulcas.herencia.interfaces;

public class Perro extends Animal implements ICorrer, INadar {

	public Perro(String nombre) {
		super(nombre);
		// TODO Auto-generated constructor stub
	}

	
	// Lo implemento porque implemento el interfaz ICorrer

	@Override
	public void correr() {
		System.out.println("Un perrito corriendo");
	}

	// Lo implemento porque implemento el interfaz INadar

	@Override
	public void nadar() {
		System.out.println("Un perrito nadando");
	}


	

	// Método abstracto de la clase madre
	@Override
	public void hacerRuido() {
		System.out.println("Guau guau");
		
	}

}

Ejemplos interfaces

package com.trifulcas.herencia.interfaces;

// El interface lo creo con la palabra clave interface
public interface IVolar {
	// Dentro del interface defino funciones SIN IMPLEMENTACION
	// Igual que los métodos abstractos son una obligación de implementar la función
	// Un interface es como un contrato
	public void volar();
}

package com.trifulcas.herencia.interfaces;

public interface INadar {
	public void nadar();
}

package com.trifulcas.herencia.interfaces;

// En la clase para implementar un interface utilizamos implements
public class Pelicano implements IVolar, INadar{

	public Pelicano() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public void volar() {
		System.out.println("Un majestuoso pelícano surcando el cielo");
		
	}

	@Override
	public void nadar() {
		System.out.println("Un pelícano nadando");
		
	}
	

}

package com.trifulcas.herencia.interfaces;

public class Murcielago implements IVolar {

	public Murcielago() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public void volar() {
		System.out.println("Un murciélago volando en la noche");
		
	}

}

package com.trifulcas.herencia.interfaces;

public class Avion implements IVolar {

	public Avion() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public void volar() {
		System.out.println("Un avión surcando raudo las nubes");
		
	}

}

package com.trifulcas.herencia.interfaces;

public class Delfin implements INadar {

	@Override
	public void nadar() {
		System.out.println("Un esbelto delfín surcando las procelosas aguas del océano");
	}

}

// Lista de elementos que implementan IVolar
		ArrayList<IVolar> elementos=new ArrayList<>();
		Pelicano p=new Pelicano();
		Murcielago m=new Murcielago();
		Avion a=new Avion();
		// Añadir a la lista cualquier clase que implemente IVolar
		elementos.add(a);
		elementos.add(p);
		elementos.add(m);
		
		// Recorrer la lista con un elemento de tipo IVolar
		for(IVolar elemento:elementos) {
			elemento.volar();
		}
		
		// Lista de elementos que implementan INadar
		ArrayList<INadar> nadadores=new ArrayList<>();
		Delfin f=new Delfin();
		nadadores.add(f);
		nadadores.add(p);
		
		// Recorrer la lista con un elemento de tipo INadar
				for(INadar elemento:nadadores) {
					elemento.nadar();
				}

Clases abstractas con métodos abstractos

package com.trifulcas.herencia.abstraccion;

public abstract class FiguraGeometrica {
	private int lados;

	public FiguraGeometrica(int lados) {
		super();
		this.lados = lados;
	}

	/**
	 * @return the lados
	 */
	public int getLados() {
		return lados;
	}

	/**
	 * @param lados the lados to set
	 */
	public void setLados(int lados) {
		this.lados = lados;
	}
	
	// En una clase abstracta puedo crear métodos abstractos
	// Los métodos abstractos tienen la palabra clave abstract
	// Y no tienen implementación: Son como una plantilla
	// Obligo a todas las clases derivadas a implementar este método
	public abstract double area();

	@Override
	public String toString() {
		return "FiguraGeometrica [lados=" + lados + "]";
	}
	
}

package com.trifulcas.herencia.abstraccion;

public class Cuadrado extends FiguraGeometrica {
	private int lado;
	public Cuadrado(int lado) {
		super(4);
		this.lado=lado;
	}

	@Override
	public double area() {
		return lado*lado;
	}
	
}

package com.trifulcas.herencia.abstraccion;

public class Triangulo extends FiguraGeometrica {

	public Triangulo() {
		super(3);
	}

	@Override
	public double area() {
		// TODO Auto-generated method stub
		return 0;
	}

	
}

//	FiguraGeometrica foo=new FiguraGeometrica(3);
		
		Cuadrado c=new Cuadrado(2);
		Triangulo t=new Triangulo();
		System.out.println(c);
		System.out.println(t);
		
		ArrayList<FiguraGeometrica> figuras=new ArrayList<>();
		figuras.add(t);
		figuras.add(c);
		
		for(FiguraGeometrica f: figuras) {
			System.out.println(f.area());
		}

Abstracción y polimorfismo

package com.trifulcas.herencia.abstraccion;

public abstract class Empleado {
	private String nombre;
	// Visible dentro de la propia clase y sus derivadas
	protected double sueldo;
	private double irpf=.85;
	
	
	public Empleado(String nombre, double sueldo) {
		super();
		this.nombre = nombre;
		this.sueldo = sueldo;
	}
	/**
	 * @return the nombre
	 */
	public String getNombre() {
		return nombre;
	}
	/**
	 * @param nombre the nombre to set
	 */
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}
	/**
	 * @return the sueldo
	 */
	public double getSueldo() {
		return sueldo;
	}
	/**
	 * @param sueldo the sueldo to set
	 */
	public void setSueldo(double sueldo) {
		this.sueldo = sueldo;
	}
	
	@Override
	public String toString() {
		return "Empleado [nombre=" + nombre + ", sueldo=" + sueldo + "]";
	}
	
	public double sueldoNeto() {
		return sueldo*irpf;
	}
	
}

package com.trifulcas.herencia.abstraccion;

public class Administrativo extends Empleado {
	private String departamento;
	private int antiguedad=0;
	
	/**
	 * @return the departamento
	 */
	public String getDepartamento() {
		return departamento;
	}


	/**
	 * @param departamento the departamento to set
	 */
	public void setDepartamento(String departamento) {
		this.departamento = departamento;
	}


	/**
	 * @return the antiguedad
	 */
	public int getAntiguedad() {
		return antiguedad;
	}


	/**
	 * @param antiguedad the antiguedad to set
	 */
	public void setAntiguedad(int antiguedad) {
		this.antiguedad = antiguedad;
	}


	public Administrativo(String nombre, double sueldo) {
		super(nombre, sueldo);
		// TODO Auto-generated constructor stub
	}

	@Override
	public double sueldoNeto() {
		// Llamo al método de la clase madre que estoy sobreescribiendo
		// con la palabra reservada super
		return super.sueldoNeto()+antiguedad*100;
	}
}

package com.trifulcas.herencia.abstraccion;

public class Comercial extends Empleado {
	
	private double comision;
	private double ventas;
	
	public Comercial(String nombre, double sueldo, double comision) {
		// Llamo al constructor de la clase madre
		super(nombre, sueldo);
		// Inicializo las propiedades de mi propia clase
		this.comision=comision;
	}
	
	/**
	 * @return the comision
	 */
	public double getComision() {
		return comision;
	}
	/**
	 * @param comision the comision to set
	 */
	public void setComision(double comision) {
		this.comision = comision;
	}
	/**
	 * @return the ventas
	 */
	public double getVentas() {
		return ventas;
	}
	/**
	 * @param ventas the ventas to set
	 */
	public void setVentas(double ventas) {
		this.ventas = ventas;
	}
	// El sueldo de un comercial es el sueldo menos el irpf
	// mas la comisión por las ventas
	// SObre escribo el método
	@Override
	public double sueldoNeto() {
		// Llamo al método de la clase madre que estoy sobreescribiendo
		// con la palabra reservada super
		return super.sueldoNeto()+comision*ventas;
	}
	
	
}

// La clase Empleado es abstracta, por lo tanto no puedo instanciar
		// Da error Empleado emp=new Empleado("foo",3000);

		// Pero eso no impide que, en aras del polimorfismo, tengamos variables
		// (e incluso listas) de tipo empleado
		ArrayList<Empleado> empresa=new ArrayList<>();
		
		// Estas variables se pueden instanciar porque sus clases no son abstractas
		Comercial ana=new Comercial("Ana",2000,.02);
		Administrativo eva=new Administrativo("Eva",2000);
		Comercial pep=new Comercial("Pepe",1000,.04);
		
		// Y las podemos añadir a una lista de empleados porque derivan de ella
		// (Igual que lo podíamos hacer antes)
		// Esto no es problemático, porque no instanciamos Empleado, sino las clases derivadas
		empresa.add(pep);
		empresa.add(eva);
		empresa.add(ana);
		
		// Podemos recorrer la lista con una variable 'empleado'
		for(Empleado emp:empresa) {
			System.out.println(emp.getSueldo());
		}

Solución 2.0

package com.trifulcas.herencia;

public class Vehiculo {
	private int velocidad;
	private int direccion;
	protected int velocidadMaxima;
	protected int aceleracion;
	protected int giro;

	public Vehiculo() {
		velocidadMaxima = 200;
		aceleracion=10;
		giro=10;
	}

	public void acelerar() {
		velocidad += aceleracion;
		if (velocidad > velocidadMaxima) {
			velocidad = velocidadMaxima;
		}
	}

	public void frenar() {
		velocidad -= aceleracion;
		if (velocidad < 0) {
			velocidad = 0;
		}
	}

	public void izquierda() {
		direccion += giro;
		if (direccion >= 360) {
			direccion -= 360;
		}
	}

	public void derecha() {
		direccion -= giro;
		if (direccion < 0) {
			direccion += 360;
		}
	}

	@Override
	public String toString() {
		return "Vehiculo [velocidad=" + velocidad + ", direccion=" + direccion + "]";
	}

}

package com.trifulcas.herencia;

public class Coche extends Vehiculo {
	public Coche() {
		velocidadMaxima=150;
	}
	
}

package com.trifulcas.herencia;

public class Bicicleta extends Vehiculo {
	public Bicicleta() {
		aceleracion=3;
	}
}

package com.trifulcas.herencia;

public class Tanque extends Vehiculo {
	public Tanque() {
		giro=90;
	}
}

Soluciones ejercicios

package com.trifulcas.herencia;

public class Producto {
	protected String nombre;
	protected String familia;

	public Producto(String nombre, String familia) {
		super();
		this.nombre = nombre;
		this.familia = familia;
	}

	/**
	 * @return the nombre
	 */
	public String getNombre() {
		return nombre;
	}

	/**
	 * @param nombre the nombre to set
	 */
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	/**
	 * @return the familia
	 */
	public String getFamilia() {
		return familia;
	}

	/**
	 * @param familia the familia to set
	 */
	public void setFamilia(String familia) {
		this.familia = familia;
	}

	@Override
	public String toString() {
		return "Producto [nombre=" + nombre + ", familia=" + familia + "]";
	}

}

package com.trifulcas.herencia;

public class Asiento extends Producto {
	protected int numeroPatas;
	
	public Asiento(String nombre, String familia, int numeroPatas) {
		super(nombre, familia);
		this.numeroPatas=numeroPatas;
	}

}

package com.trifulcas.herencia;

public class Silla extends Asiento{

	public Silla(String nombre, String familia, int numeroPatas) {
		super(nombre, familia, numeroPatas);
		
	}

}

package com.trifulcas.herencia;

public class Sillon extends Asiento {

	public Sillon(String nombre, String familia, int numeroPatas) {
		super(nombre, familia, numeroPatas);
	}

}

package com.trifulcas.herencia;

public class Vehiculo {
	protected int velocidad;
	protected int direccion;
	
	public void acelerar() {
		velocidad+=10;
		if (velocidad>200) {
			velocidad=200;
		}
	}
	public void frenar() {
		velocidad-=10;
		if (velocidad<0) {
			velocidad=0;
		}
	}
	public void izquierda() {
		direccion+=10;
		if (direccion>=360) {
			direccion-=360;
		}
	}
	public void derecha() {
		direccion-=10;
		if (direccion<0) {
			direccion+=360;
		}
	}
	@Override
	public String toString() {
		return "Vehiculo [velocidad=" + velocidad + ", direccion=" + direccion + "]";
	}
	
}

package com.trifulcas.herencia;

public class Coche extends Vehiculo {
	public void acelerar() {
		velocidad+=10;
		if (velocidad>150) {
			velocidad=150;
		}
	}
}

package com.trifulcas.herencia;

public class Bicicleta extends Vehiculo {
	public void acelerar() {
		velocidad+=3;
		if (velocidad>200) {
			velocidad=200;
		}
	}
	public void frenar() {
		velocidad-=3;
		if (velocidad<0) {
			velocidad=0;
		}
	}
}

package com.trifulcas.herencia;

public class Tanque extends Vehiculo {
	public void izquierda() {
		direccion+=90;
		if (direccion>=360) {
			direccion-=360;
		}
	}
	public void derecha() {
		direccion-=90;
		if (direccion<0) {
			direccion+=360;
		}
	}
}