En este ejercicio se escribirá un programa Java que usa clases abstractas. También se expondrá cómo añadir comportamiento polimórfico al programa a través de métodos abstractos.
1. Crear un nuevo proyecto NetBeans
package
myabstractclassproject; // The LivingThing class is an abstract class because // some methods in it are declared as abstract methods. public abstract class LivingThing { private String name; public LivingThing(String name){ this.name = name; } public void breath(){ System.out.println("Living Thing breathing..."); } public void eat(){ System.out.println("Living Thing eating..."); } /** * Abstract method walk() * We want this method to be implemented by subclasses of * LivingThing */ public abstract void walk(); public String getName() { return name; } public void setName(String name) { this.name = name; } } |
package
myabstractclassproject; public class Human extends LivingThing { public Human(String name){ super(name); } // Provide implementation of the abstract method. public void walk(){ System.out.println("Human " + getName() + " walks..."); } } |
package
myabstractclassproject; public class Monkey extends LivingThing { public Monkey(String name){ super(name); } // Implement the abstract method public void walk(){ System.out.println("Monkey " + getName() + " also walks..."); } } |
package
myabstractclassproject; public class Main { public static void main(String[] args) { // Create Human object instance // and assign it to Human type. Human human1 = new Human("Sang Shin"); human1.walk(); // Create Human object instance // and assign it to LivingThing type. LivingThing livingthing1 = human1; livingthing1.walk(); // Create a Monkey object instance // and assign it to LivingThing type. LivingThing livingthing2 = new Monkey("MonkeyWrench"); livingthing2.walk(); // Display data from human1 and livingthing1. // Observe that they refer to the same object instance. System.out.println("human1.getName() = " + human1.getName()); System.out.println("livingthing1.getName() = " + livingthing1.getName()); // Check of object instance that is referred by x and // y is the same object instance. boolean b1 = (human1 == livingthing1); System.out.println("Do human1 and livingthing1 point to the same object instance? " + b1); // Compile error // LivingThing z = new LivingThing(); } } |
Human Sang Shin walks... Human Sang Shin walks... Monkey MonkeyWrench also walks... human1.getName() = Sang Shin livingthing1.getName() = Sang Shin Do human1 and livingthing1 point to the same object instance? true |
En este paso se va a reescribir el programa MyOnlineShop que se compiló y ejecutó en el Laboratorio Java Inheritance para usar un método abstracto de una clase abstracta (en lugar de overriding un método de una clase concreta). Las diferencias se muestran en negrita.
Las siguientes instrucciones asumen que se parte de cero.
1. Crear un proyecto NetBeans
package myonlineshop; // Product class is now an abstract class public abstract class Product { private double regularPrice; /** Creates a new instance of Product */ public Product(double regularPrice) { this.regularPrice = regularPrice; } // computeSalePrice() is now an abstract method public abstract double computeSalePrice(); public double getRegularPrice() { return regularPrice; } public void setRegularPrice(double regularPrice) { this.regularPrice = regularPrice; } } |
package myonlineshop; // Electronics class is now an abstract class because // it does not provide implementation of the // computeSalePrice() abstract method. public abstract class Electronics extends Product{ private String manufacturer; /** Creates a new instance of Electronics */ public Electronics(double regularPrice, String manufacturer) { super(regularPrice); this.manufacturer = manufacturer; } public String getManufacturer() { return manufacturer; } public void setManufacturer(String manufacturer) { this.manufacturer = manufacturer; } } |
package myonlineshop; public class MP3Player extends Electronics{ private String color; public MP3Player(double regularPrice, String manufacturer, String color) { super(regularPrice, manufacturer); this.color = color; } // Implement the abstract method public double computeSalePrice(){ return super.getRegularPrice() * 0.9; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } } |
package myonlineshop; public class TV extends Electronics { int size; /** Creates a new instance of TV */ public TV(double regularPrice, String manufacturer, int size) { super(regularPrice, manufacturer); this.size = size; } // Implement the abstract method public double computeSalePrice(){ return super.getRegularPrice() * 0.8; } } |
package myonlineshop; public class Book extends Product{ private String publisher; private int yearPublished; /** Creates a new instance of Book */ public Book(double regularPrice, String publisher, int yearPublished) { super(regularPrice); this.publisher = publisher; this.yearPublished = yearPublished; } // Implement the abstract method public double computeSalePrice(){ return super.getRegularPrice() * 0.5; } public String getPublisher() { return publisher; } public void setPublisher(String publisher) { this.publisher = publisher; } public int getYearPublished() { return yearPublished; } public void setYearPublished(int yearPublished) { this.yearPublished = yearPublished; } } |
package myonlineshop; public class Main { public static void main(String[] args) { // Declare and create Product array of size 5 Product[] pa = new Product[5]; // Create object instances and assign them to // the type of Product. pa[0] = new TV(1000, "Samsung", 30); pa[1] = new TV(2000, "Sony", 50); pa[2] = new MP3Player(250, "Apple", "blue"); pa[3] = new Book(34, "Sun press", 1992); pa[4] = new Book(15, "Korea press", 1986); // Compute total regular price and total // sale price. double totalRegularPrice = 0; double totalSalePrice = 0; for (int i=0; i<pa.length; i++){ // Call a method of the super class to get // the regular price. totalRegularPrice += pa[i].getRegularPrice(); // Since the sale price is computed differently // depending on the product type, overriding (implementation) // method of the object instance of the sub-class // gets invoked. This is runtime polymorphic // behavior. totalSalePrice += pa[i].computeSalePrice(); System.out.println("Item number " + i + ": Type = " + pa[i].getClass().getName() + ", Regular price = " + pa[i].getRegularPrice() + ", Sale price = " + pa[i].computeSalePrice()); } System.out.println("totalRegularPrice = " + totalRegularPrice); System.out.println("totalSalePrice = " + totalSalePrice); } } |
Item number 0: Type = myonlineshop.TV,
Regular price = 1000.0, Sale price = 800.0 Item number 1: Type = myonlineshop.TV, Regular price = 2000.0, Sale price = 1600.0 Item number 2: Type = myonlineshop.MP3Player, Regular price = 250.0, Sale price = 225.0 Item number 3: Type = myonlineshop.Book, Regular price = 34.0, Sale price = 17.0 Item number 4: Type = myonlineshop.Book, Regular price = 15.0, Sale price = 7.5 totalRegularPrice = 3299.0 totalSalePrice = 2649.5 |
En este ejercicio se ha desarrollado un programa simple usando una clase abstracta. También se ha visto cómo añadir comportamiento polimórfico al programa mediante el uso de métodos abstractos.
En este ejercicio se desarrollará una aplicación Java
que usa una Interface como un tipo.
1. Crear un proyecto NetBeans
package
mypersoninterfaceproject; public interface PersonInterface { // Compute person's total wealth int computeTotalWealth(); // Get person's name String getName(); } |
package
mypersoninterfaceproject; public class Person implements PersonInterface { int cashSaving; int retirementFund; String firstName; String lastName; // Constructor with arguments Person(int cashSaving, int retirementFund, String firstName, String lastName){ this.cashSaving = cashSaving; this.retirementFund = retirementFund; this.firstName = firstName; this.lastName = lastName; } // Compute person's total wealth public int computeTotalWealth(){ System.out.println((cashSaving + retirementFund));; return (cashSaving + retirementFund); } // Get person's name public String getName(){ return firstName + " " + lastName; } } |
package
mypersoninterfaceproject; public class Main { public static void main(String[] args) { // Create an object instance of Person class. Person person1 = new Person(10000, 20000, "Sang", "Shin"); // You can assign the object instance to // PersonInterface type. PersonInterface personinterface1 = person1; // Display data from person1 and personinterface1. // Observe that they refer to the same object instance. System.out.println("person1.getName() = " + person1.getName() + "," + " person1.computeTotalWealth() = " + person1.computeTotalWealth()); System.out.println("personinterface1.getName() = " + personinterface1.getName() + "," + " personinterface1.computeTotalWealth() = " + personinterface1.computeTotalWealth()); // Check of object instance that is referred by person1 and // personinterface1 is the same object instance. boolean b1 = (person1 == personinterface1); System.out.println("Do person1 and personinterface1 point to the same object instance? " + b1); // Create an object instance of Person class // and assign it to the interface type directly. PersonInterface personinterface2 = new Person(3000, 4000, "Dadu", "Daniel"); System.out.println("personinterface2.getName() = " + personinterface2.getName() + "," + " personinterface2.computeTotalWealth() = " + personinterface2.computeTotalWealth()); } } |
30000 person1.getName() = Sang Shin, person1.computeTotalWealth() = 30000 30000 personinterface1.getName() = Sang Shin, personinterface1.computeTotalWealth() = 30000 Do person1 and personinterface1 point to the same object instance? true 7000 personinterface2.getName() = Dadu Daniel, personinterface2.computeTotalWealth() = 7000 |
En este paso se desarrolla otro programa Java
que usa la interface llamada RelationInterface.
1. Crear un proyecto NetBeans
package
myrelationinterfaceproject; // Define an interface with three abstract methods. // Any class that implements this interface has to // implement all three methods. public interface RelationInterface { public boolean isGreater( Object a, Object b); public boolean isLess( Object a, Object b); public boolean isEqual( Object a, Object b); } |
package
myrelationinterfaceproject; public class Line implements RelationInterface{ private double x1; private double x2; private double y1; private double y2; // Constructor methoe of the Line class. public Line(double x1,double x2,double y1,double y2){ this.x1 = x1; this.x2 = x2; this.y1 = y1; this.y2 = y2; } // A new method definition of the Line class public double getLength(){ double length = Math.sqrt( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)); return length; } // Implement isGreater(..) method defined in the Relation interface public boolean isGreater( Object a, Object b){ double aLen = ((Line)a).getLength(); double bLen = ((Line)b).getLength(); return (aLen > bLen); } // Implement isLess(..) method defined in the Relation interface public boolean isLess( Object a, Object b){ double aLen = ((Line)a).getLength(); double bLen = ((Line)b).getLength(); return (aLen < bLen); } // Implement isEqual(..) method defined in the Relation interface public boolean isEqual( Object a, Object b){ double aLen = ((Line)a).getLength(); double bLen = ((Line)b).getLength(); return (aLen == bLen); } } |
package
myrelationinterfaceproject; public class Main { public static void main(String[] args) { // Create two Line object instances. Line line1 = new Line(1.0, 2.0, 1.0, 2.0); Line line2 = new Line(2.0, 3.0, 2.0, 3.0); boolean b1 = line1.isGreater(line1, line2); System.out.println("line1 is greater than line2: " + b1); boolean b2 = line1.isEqual(line1, line2); System.out.println("line1 is equal with line2: " + b2); // Note that the line3 is object instance of Line type. // Because the Line type is also a type of RelationInterface, // the line3 variable can be declared as RelationInterface type. // This is a very very important concept you need to understand. RelationInterface line3 = new Line(1.0, 5.0, 1.0, 5.0); boolean b3 = line3.isEqual(line1, line3); System.out.println("line1 is equal with line3: " + b3); System.out.println("Length of line1 is " + line1.getLength()); System.out.println("Length of line2 is " + line2.getLength()); // The following line of code will generate a compile error since line3 // is declared as RelationInterface interface type not Line type // and the getLength() method is not one of the methods defined // in the RelationInterface interface. It is commented out for now. // System.out.println("Length of line3 is " + line3.getLength()); } } |
line1 is greater than line2:
false line1 is equal with line2: true line1 is equal with line3: false Length of line1 is 1.4142135623730951 Length of line2 is 1.4142135623730951 |
En este ejercicio se ha construído dos programas Java que usan interfaces. Se ha visto cómo usar una interface como un tipo y cómo una clase concreta implementa una interface.
Volver al inicio
En este ejercicio se estudia cómo una clase concreta puede implementar varias interfaces Java.
package
mypersoninterfaceproject; public interface AnotherInterfaceExample { // Measure person's intelligence int measureIntelligence(String name); } |
package
mypersoninterfaceproject; public class Person implements PersonInterface, AnotherInterfaceExample{ int cashSaving; int retirementFund; String firstName; String lastName; // Constructor with arguments Person(int cashSaving, int retirementFund, String firstName, String lastName){ this.cashSaving = cashSaving; this.retirementFund = retirementFund; this.firstName = firstName; this.lastName = lastName; } // Compute person's total wealth public int computeTotalWealth(){ System.out.println((cashSaving + retirementFund));; return (cashSaving + retirementFund); } // Get person's name public String getName(){ return firstName + " " + lastName; } // Implement method of AnotherInterfaceExample public int measureIntelligence(String name){ if (name.startsWith("smart")){ return 100; } else{ return 50; } } } |
package mypersoninterfaceproject;
public class Main { public static void main(String[] args) { // Create an object instance of Person class. Person person1 = new Person(10000, 20000, "Sang", "Shin"); // You can assign the object instance to // PersonInterface type. PersonInterface personinterface1 = person1; // Display data from person1 and personinterface1. // Observe that they refer to the same object instance. System.out.println("person1.getName() = " + person1.getName() + "," + " person1.computeTotalWealth() = " + person1.computeTotalWealth() + "," + " person1.measureIntelligence() = " + person1.measureIntelligence(person1.getName())); System.out.println("personinterface1.getName() = " + personinterface1.getName() + "," + " personinterface1.computeTotalWealth() = " + personinterface1.computeTotalWealth()); // Compile error is expected on the following line of code. // personinterface1.measureIntelligence(personinterface1.getName()); // You can assign the object instance to // AnotherInterfaceExample type. AnotherInterfaceExample anotherinterfaceexample1 = person1; // Check of object instance that is referred by personinterface1 and // anotherinterfaceexample1 is the same object instance. boolean b1 = (personinterface1 == anotherinterfaceexample1); System.out.println("Do personinterface1 and anotherinterfaceexample1 point to the same object instance? " + b1); } } |
4. Compilar y ejecutar el programa.
30000 person1.getName() = Sang Shin, person1.computeTotalWealth() = 30000, person1.measureIntelligence() = 50 30000 personinterface1.getName() = Sang Shin, personinterface1.computeTotalWealth() = 30000 Do personinterface1 and anotherinterfaceexample1 point to the same object instance? true |
En este ejercicio se ha modificado el proyecto
MyPersonInterfaceProject para que tenga la clase Person que implementa varias interfaces .
En este ejercicio, se va a reescribir el programa MyOnlineShopUsingAbstractClass desarrollado anteriormente para usar una interface (en lugar de clase abstracta).
package
myonlineshopusinginterface; public interface ProductInterface { public double computeSalePrice(); public double getRegularPrice(); public void setRegularPrice(double regularPrice); } |
package
myonlineshopusinginterface; public class Product implements ProductInterface{ private double regularPrice; /** Creates a new instance of Product */ public Product(double regularPrice) { this.regularPrice = regularPrice; } // Implement the methods of the ProductInterface public double computeSalePrice(){ return 0; } public double getRegularPrice() { return regularPrice; } public void setRegularPrice(double regularPrice) { this.regularPrice = regularPrice; } } |
package
myonlineshopusinginterface; public interface ElectronicsInterface extends ProductInterface { public String getManufacturer(); } |
package
myonlineshopusinginterface; public class Electronics extends Product implements ElectronicsInterface { private String manufacturer; /** Creates a new instance of Electronics */ public Electronics(double regularPrice, String manufacturer) { super(regularPrice); this.manufacturer = manufacturer; } public String getManufacturer() { return manufacturer; } public void setManufacturer(String manufacturer) { this.manufacturer = manufacturer; } } |
package
myonlineshopusinginterface; public class MP3Player extends Electronics{ private String color; public MP3Player(double regularPrice, String manufacturer, String color) { super(regularPrice, manufacturer); this.color = color; } // Override the method public double computeSalePrice(){ return super.getRegularPrice() * 0.9; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } } |
package
myonlineshopusinginterface; public class TV extends Electronics { int size; /** Creates a new instance of TV */ public TV(double regularPrice, String manufacturer, int size) { super(regularPrice, manufacturer); this.size = size; } // Override the method public double computeSalePrice(){ return super.getRegularPrice() * 0.8; } } |
package
myonlineshopusinginterface; public class Book extends Product { private String publisher; private int yearPublished; /** Creates a new instance of Book */ public Book(double regularPrice, String publisher, int yearPublished) { super(regularPrice); this.publisher = publisher; this.yearPublished = yearPublished; } // Override the method public double computeSalePrice(){ return super.getRegularPrice() * 0.5; } public String getPublisher() { return publisher; } public void setPublisher(String publisher) { this.publisher = publisher; } public int getYearPublished() { return yearPublished; } public void setYearPublished(int yearPublished) { this.yearPublished = yearPublished; } } |
package
myonlineshopusinginterface; public class Main { /** Creates a new instance of Main */ public Main() { } public static void main(String[] args) { // Declare and create Product array of size 5 ProductInterface[] pa = new Product[5]; // Create object instances and assign them to // the type of Product. pa[0] = new TV(1000, "Samsung", 30); pa[1] = new TV(2000, "Sony", 50); pa[2] = new MP3Player(250, "Apple", "blue"); pa[3] = new Book(34, "Sun press", 1992); pa[4] = new Book(15, "Korea press", 1986); // Compute total regular price and total // sale price. double totalRegularPrice = 0; double totalSalePrice = 0; for (int i=0; i<pa.length; i++){ // Call a method of the super class to get // the regular price. totalRegularPrice += pa[i].getRegularPrice(); // Since the sale price is computed differently // depending on the product type, overriding (implementation) // method of the object instance of the sub-class // gets invoked. This is runtime polymorphic // behavior. totalSalePrice += pa[i].computeSalePrice(); System.out.println("Item number " + i + ": Type = " + pa[i].getClass().getName() + ", Regular price = " + pa[i].getRegularPrice() + ", Sale price = " + pa[i].computeSalePrice()); } System.out.println("totalRegularPrice = " + totalRegularPrice); System.out.println("totalSalePrice = " + totalSalePrice); } } |
4. Compilar y ejecutar el programa
Item number 0: Type =
myonlineshopusinginterface.TV, Regular price = 1000.0, Sale price =
800.0 Item number 1: Type = myonlineshopusinginterface.TV, Regular price = 2000.0, Sale price = 1600.0 Item number 2: Type = myonlineshopusinginterface.MP3Player, Regular price = 250.0, Sale price = 225.0 Item number 3: Type = myonlineshopusinginterface.Book, Regular price = 34.0, Sale price = 17.0 Item number 4: Type = myonlineshopusinginterface.Book, Regular price = 15.0, Sale price = 7.5 totalRegularPrice = 3299.0 totalSalePrice = 2649.5 |
En este ejercicio se ha reescrito la aplicación MyOnlineShop
usando iterfaces.
Las interfaces pueden tener una relación de herencia entre ellas.
package mypersoninterfaceproject; // StudentInterface interface extends PersonInteface interface public interface StudentInterface extends PersonInterface{ // Find the school the student attends String findSchool(); } |
package
mypersoninterfaceproject; public class Student implements StudentInterface { int cashSaving; int retirementFund; String firstName; String lastName; String school; // Constructor with arguments Student(int cashSaving, int retirementFund, String firstName, String lastName, String school){ this.cashSaving = cashSaving; this.retirementFund = retirementFund; this.firstName = firstName; this.lastName = lastName; this.school = school; } // Compute person's total wealth public int computeTotalWealth(){ System.out.println((cashSaving + retirementFund)); return (cashSaving + retirementFund); } // Get person's name public String getName(){ return firstName + " " + lastName; } // Find out the school the student attends public String findSchool(){ return school; } } |
package
mypersoninterfaceproject; public class Main { public static void main(String[] args) { // Create an object instance of Student class. Student student1 = new Student(10000, 20000, "Sang", "Shin", "Good School"); // You can assign the object instance to // StudentInterface type. StudentInterface studentinterface1 = student1; // Display data from student1 and studentinterface1. // Observe that they refer to the same object instance. System.out.println("student1.getName() = " + student1.getName() + "," + " student1.computeTotalWealth() = " + student1.computeTotalWealth()+ "," + " student1.findSchool() = " + student1.findSchool()); System.out.println("studentinterface1.getName() = " + studentinterface1.getName() + "," + " studentinterface1.computeTotalWealth() = " + studentinterface1.computeTotalWealth()+ "," + " studentinterface1.findSchool() = " + studentinterface1.findSchool()); // Check of object instance that is referred by student1 and // studentinterface1 is the same object instance. boolean b1 = (student1 == studentinterface1); System.out.println("Do student1 and studentinterface1 point to the same object instance? " + b1); } } |
4. Compilar y ejecutar el programa
30000 student1.getName() = Sang Shin, student1.computeTotalWealth() = 30000, student1.findSchool() = Good School 30000 studentinterface1.getName() = Sang Shin, studentinterface1.computeTotalWealth() = 30000, studentinterface1.findSchool() = Good School Do student1 and studentinterface1 point to the same object instance? true |
En este ejercicio se ha desarrollado un programa que usa una interface que es una hija de otra
interface.
package
mypersoninterfaceproject; public interface PersonInterface { // Compute person's total wealth int computeTotalWealth(); // Get person's name String getName(); // Add another method to the interface void newMethod(); } |
3. Eliminar el cambio realizado en PersonInterface.java en el paso anterior como se muestra en Código-6.13. Este es el código original antes del cambio.
package
mypersoninterfaceproject; public interface PersonInterface { // Compute person's total wealth int computeTotalWealth(); // Get person's name String getName(); } |
package
mypersoninterfaceproject; public interface PersonInterfaceAnother { // Add another method to the interface void newMethod(); } |
package
mypersoninterfaceproject; public class PersonAnother implements PersonInterface, PersonInterfaceAnother{ int cashSaving; int retirementFund; String firstName; String lastName; // Constructor with arguments PersonAnother(int cashSaving, int retirementFund, String firstName, String lastName){ this.cashSaving = cashSaving; this.retirementFund = retirementFund; this.firstName = firstName; this.lastName = lastName; } // Compute person's total wealth public int computeTotalWealth(){ System.out.println((cashSaving + retirementFund)); return (cashSaving + retirementFund); } // Get person's name public String getName(){ return firstName + " " + lastName; } // Implement a new method public void newMethod(){ // Some code } } |
package
mypersoninterfaceproject; public class PersonAnother2 extends Person implements PersonInterfaceAnother{ PersonAnother2(){ } // Implement a new method public void newMethod(){ // Some code } } |
En este ejercicio se ha visto cómo añadir nuevos métodos a la interface sin alterar el código que depende de la interface existente.