Spaces:
Running
Running
| It is common that there is a PROPERTY we would like to declare for MULTIPLE CLASSES. | |
| For example, we could have several classes that have a price. | |
| However, since a price can be attached to very different classes (for example a car, a banana, an airplane, and a house), | |
| it would be difficult to come up with a common superclass. | |
| For this, we have INTERFACES. | |
| The idea of an interface is that it DEFINES a PROPERTY THAT the CLASSES CAN then IMPLEMENT. | |
| In practice, the interface (which is a sort of CLASS ITSELF) TYPICALLY DEFINES a METHOD or METHODS WITHOUT actual IMPLEMENTATION. | |
| The classes that implement the interface then implement the method(s) as well. | |
| This enables the grouping of objects based on a single property, | |
| even if the objects themselves are very different (for example a banana and an airplane). | |
| This way we can for example calculate the total price of different objects with price by using a simple loop. | |
| ======================================== | |
| Interfaces in Java | |
| In Java, an interface is defined with the keyword 'interface'. | |
| Inside the interface, ALL DECLARED MEMBERS are PUBLIC, because the implementing classes need to PROVIDE the MEMBERS TO their CLIENTS. | |
| For example, see the interface 'Priced': | |
| interface Priced { | |
| int getPrice(); | |
| } | |
| Note that getPrice() is a 'method declaration'. | |
| VISIBILITY MODIFIERS are NOT NEEDED, since ALL the MEMBERS defined in the interface are PUBLIC. | |
| As seen in the example, 'no implementations for the methods are given' in the interface. | |
| The interface is implemented with keyword 'implements' (different from 'extends', which is used when we extend a class). | |
| class Car implements Priced { | |
| private String manufacturer; | |
| private String model; | |
| private int price; | |
| public Car(String manufacturer, String model, int price) { | |
| this.manufacturer = manufacturer; | |
| this.model = model; | |
| this.price = price; | |
| } | |
| // update method | |
| @Override | |
| public int getPrice() { | |
| return price; | |
| } | |
| } | |
| As a second example, let's look at class Banana. | |
| This time the price is fixed at 5. | |
| This does not make a difference, the interface just defines that the class needs to return an integer from the method getPrice(). | |
| class Banana implements Priced { | |
| double length; | |
| public Banana(double length) { | |
| this.length = length; | |
| } | |
| @Override | |
| public int getPrice() { | |
| return 5; | |
| } | |
| } | |
| The implementing classes can have a very different basic idea. | |
| However, they need to implement the method getPrice() which is defined in the interface. | |
| public class Test { | |
| public static void main(String[] args) { | |
| Car car = new Car("Volvo", "345", 1500); | |
| Banana banana = new Banana(15.25); | |
| System.out.println(car.getPrice()); | |
| System.out.println(banana.getPrice()); | |
| } | |
| } | |
| Program outputs: | |
| 1500 | |
| 5 | |
| ======================================== | |
| In the newer versions of Java, interface methods can have default implementations. | |
| This helps for example when you need to make changes in the interface. | |
| The feature is not discussed in detail in this course, more information can be found e.g. at: | |
| https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html | |
| ======================================== | |
| Let's see a second example, an interface called Measurable which defines methods getWidth and getHeight. | |
| interface Measurable { | |
| double getWidth(); | |
| double getHeight(); | |
| } | |
| Now the implementing classes MUST IMPLEMENT BOTH METHODS: | |
| class Block implements Measurable { | |
| private String material; | |
| private double width; | |
| private double height; | |
| public Block(String material, double width, double height) { | |
| this.material = material; | |
| this.width = width; | |
| this.height = height; | |
| } | |
| //////////////////// | |
| // HERE | |
| //////////////////// | |
| @Override | |
| public double getWidth() { | |
| return width; | |
| } | |
| @Override | |
| public double getHeight() { | |
| return height; | |
| } | |
| //////////////////// | |
| public String getMaterial() { | |
| return material; | |
| } | |
| } | |
| A class can implement more than one interface: | |
| class Block implements Measurable, Priced { | |
| private String material; | |
| private double width; | |
| private double height; | |
| public Block(String material, double width, double height) { | |
| this.material = material; | |
| this.width = width; | |
| this.height = height; | |
| } | |
| //////////////////// | |
| // HERE | |
| //////////////////// | |
| @Override | |
| public double getWidth() { | |
| return width; | |
| } | |
| @Override | |
| public double getHeight() { | |
| return height; | |
| } | |
| @Override | |
| public int getPrice() { | |
| return 25; | |
| } | |
| //////////////////// | |
| public String getMaterial() { | |
| return material; | |
| } | |
| } | |