Loading…

Interfaces

I believe that the one who else introduced the idea of a user interface might not have thought how fantastic the sensation was in its features. Although this is just my guesswork. In any kind of case, the concept associated with the interface has extended the options of OOP very strongly.

 

So what is the interface? Essentially, this particular is a description of bare functionality without any kind of bindings towards the class functions. If to convey figuratively, the classes possess the opportunity to possess a profession – the sender of the mail, transaction manager, page distributor, controller, etc. I am right now trying to bring straight down the grandeur of this particular idea, and I realize that it is not however possible. Simply take a term – it’s great. Along with the help of interfaces, relations between objects turn out to be more flexible, which enables building the architecture of applications within much more independent blocks.

 

Again, if we return to the example with the profession, then, actually, you may not care about gender, eye colour, age group and height of the individual who works as the driver, electrician or developer. It is important to you that they know exactly how to do this function and how to do it well (to some extent). Also, it is important that both a person and a class may have several professions (apply several interfaces). If return to the inheritance topic, then, it is nicely known, a class could be inherited ONLY FROM A SINGLE class. However, it can have quite a lot of interfaces.

 

Let’s move from words to deeds – back to our class Robot.

Last time we taught it to move and memorize its route for display on the form. When creating it, we ran a little forward – I introduced the class, which we will certainly not discuss for a few time – ArrayList. Till we discuss it – I’ll just note once again that this class allows you to work with dynamic lists of objects – add, delete, view, iterate. Let’s expand the capabilities of our robot – we will give it the ability to tell someone that it started to move forward and stopped. It is possibly not such a useless thing – for example when observing the rover.

 

Let’s focus our attention on the words “inform someone”. This is a very delicate moment – the robot, after all, doesn’t really matter to whom to report. Here it is, the point of application of the interface – it doesn’t matter to us who will listen – it is important for us that someone or something is able to listen to our message, to comply with a specific contract. It’s time to see how the interface is defined.

 

1

2

3

4

5

6

7

8

9

10

11

12

package edu.javacourse.robot;

 

/ **

* Robot event listener interface

* /

public interface RobotListener

{

     // The method will be called at the moment of the start of movement

     public void startMove (double x, double y);

     // The method will be called at the moment of the end of movement

     public void endMove (double x, double y);

}

As you can see, the interface description is a fairly simple process – it is much more difficult to understand when it is really needed. Now, let’s consider it in some detail.

 

First, to describe the interface, you need to use the word interface. Secondly, the methods do not contain the body – at all. It is simply against the rules. Only the description is created — accessibility, return type, and input parameters. After that, we put a semicolon.

 

You may have a question – why do we pass x and y coordinates to interface methods? Quite a reasonable question, but here is also quite a reasonable answer – the robot must also report where it started and where it stopped.

 

It is time to modify the robot’s code so that, firstly, it can register the “listener”, and secondly, it must be able to work with it. Let’s take a look at the code.

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

package edu.javacourse.robot;

 

import java.util.ArrayList;

 

public class Robot

{

    private double x = 0;

    private double y = 0;

    protected double course = 0;

    private ArrayList <RobotLine> lines = new ArrayList <RobotLine> ();

    // Link to the event listener from the robot

    // Note that this is a link to the UI

    private RobotListener listener;

    

    public Robot (double x, double y) {

        this.x = x;

        this.y = y;

    }

 

    // Method to set the real listener.

    public void setListener (RobotListener listener) {

        this.listener = listener;

    }

    

    public void forward (int distance) {

        // Call the listener (if installed) at the beginning

        if (listener! = null) {

            listener.startMove (x, y);

        }

        // Remember the coordinates of the robot before moving

        final double xOld = x;

        final double yOld = y;

        // Change Coordinates

        x + = distance * Math.cos (course / 180 * Math.PI);

        y + = distance * Math.sin (course / 180 * Math.PI);

 

        // Call the listener (if installed) after stopping

        if (listener! = null) {

            listener.endMove (x, y);

        }

 

        // Remember the coordinates of the distance travelled in the list

        // The List class allows you to add an object and store it

        lines.add (new RobotLine (xOld, yOld, x, y));

    }

 

    public double getX () {

        return x;

    }

 

    public double getY () {

        return y;

    }

 

    public double getCourse () {

        return course;

    }

 

    public void setCourse (double course) {

        this.course = course;

    }

 

    public ArrayList <RobotLine> getLines () {

        return lines;

    }

}

There are three moments in our code that we should pay attention to. The first one is declaring the link to a listener. 

 

private RobotListener listener;

 

Yes, it is the same solution for objects’ relation. No magic here again – we need to tell our robot whom to sell the messages/ The second thing is that we will need a method for setting a listener:

 

1

2

3

public void setListener(RobotListener listener) {

    this.listener = listener;

}

Finally, the third thing – in method forward the robot calls the listener. Take a look – we check for NULL before the call. The matter is that if the listener is not set, then we can get a not funny NullPointer error – the pointer is empty. Such mistakes are made by pretty experienced developers as well, so you need to be attentive. It is a pretty insidious error, albeit simple in debugging.

 

This way, our robot is ready to send events and now our task is to create the same listener. ATTENTION PLEASE – you cannot create an object of interface type. It is pretty similar to an abstract class, but the abstract class contain at least some code, but the interface does not contain any. In case we return back to the profession analogy, then the existence of a doctor at the hospital means the existence of an individual who obtains a doctor’s profession. It is all the same with interfaces – we need to create a class, that implements a required interface. Yet again, a class can implement more than a single interface. Let’s now create a simple listener:

 

1

2

3

4

5

6

package edu.javacourse.robot;

 

// Наш класс реализует интерфейс robotListener

public class SimpleRobotListener implements RobotListener

{

}

As you can see, the notation is simple enough – if you want to say that the class implements the interface, you write the word implements and then specify the necessary interface. If you need to implement multiple interfaces, they are written with a comma – for example:

 

1

public MyClass implements Interface1, Interface2, Interface3

If you create a class that implements an interface, you must have methods in this class with exactly the same descriptions as in the interface. Those. Now our class will produce an error when compiled. Let’s make a simple transaction.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

package edu.javacourse.robot;

 

// Our class implements the robotListener interface

public class SimpleRobotListener implements RobotListener

{

 

     @Override

     public void startMove (double x, double y)

     {

         System.out.println (“The robot began to move, coordinates:” + x + “,” + y);

     }

 

     @Override

     public void endMove (double x, double y)

     {

         System.out.println (“The robot has finished moving, coordinates:” + x + “,” + y);

     }

}

I hope you remember what the @Override annotation means — we have already discussed this. In order not to run on the links – this is a special designation that the method is redefined.

The listener is ready – it remains only to connect it to our robot and run the program. The connection is made through a call to the setListener method. We can do this in the RobotManager class.

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

package edu.javacourse.robot;

 

import edu.javacourse.robot.ui.RobotFrame;

import javax.swing.JFrame;

 

public class RobotManager

{

 

    public static void main (String [] args)

    {

        // The number of sides of the polygon

        final int COUNT = 4;

        // Side Length

        final int SIDE = 100;

 

        Robot robot = new Robot (200, 50);

        // Set the listener for the robot

        SimpleRobotListener srl = new SimpleRobotListener ();

        robot.setListener (srl);

        // Create a closed shape with the number of corners COUNT

        for (int i = 0; i <COUNT; i ++) {

            robot.forward (SIDE);

            robot.setCourse (robot.getCourse () + 360 / COUNT);

        }

 

        // Create a form to draw the path of our robot

        RobotFrame rf = new RobotFrame (robot);

        rf.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

        rf.setVisible (true);

    }

}

 

In code, we create a SimpleRobotListener object instance which implements RobotListener interface and class Robot effortlessly allows to set a listener for it. We need to emphasize an important thing – it does not matter for class Robot what class implements the required interface. Speaking more accurately, while creating SimpleRobotListener it is recommended to write the following:

 

1

RobotListener srl = new SimpleRobotListener();

We can also recall polymorphism – the class knows how to be a robot listener (he has such a profession). And we work with an instance of the class SimpleRobotListener as with the profession RobotListener. Such abstraction is very convenient when designing – you will see it. You are not tied to specific classes – you are tied exclusively to the “profession”.

Now, when launching our program, the text that our listener should output will be visible in the output console.

Properties and constants

Due to the fact that an interface is only a description of what to do, it does not contain info about how to do (as you have already seen, the methods do not contain implementation), thus an interface cannot include properties as there is no place to call them. Here is an only exception – an interface can contain constants, something like this:

 

1

2

3

4

public interface SimpleInterface

{

    public static final String NAME = “simple name”;

}

We can address field NAME as a constant. I think that everything here is pretty obvious and easy-to-understand – you can describe constants in an interface that can be in-demand.

Moving square

Let’s consider an example that allows us to generate an online graphical application in which we will use interfaces. I am very warm to the examples that allow you to aesthetically see the work program. And graphics applications are extremely appreciative material. Therefore, our task is to create an application that will use the control keys to go a square around the screen.

There will be two buttons on the form – UPWARD and DOWN, which allow you to move the square up and down, respectively. The application itself is not difficult – it is very important see the use of interfaces.

 

Buttons are actually very similar in their idea to our robot – when clicked on in it, they are able to send events to those objects that they have registered as listeners. Moreover, the buttons are allowed to have many listeners at the same time – a whole list.

 

We give the code of the form that contains three components – 2 buttons for control along with a panel that can attract a square with particular coordinates and, which will be important to note correct away, can “listen” in order to events from the control keys. The opportunity to listen is accomplished very simply – our own panel implements the ActionListener interface (this interface will be described in the Golfing swing library). Moreover, the particular element can pay attention to events from both buttons — it is registered as a listener for both. Therefore, look at the program code:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

package edu.javacourse.move;

 

import java.awt.BorderLayout;

import javax.swing.JButton;

import javax.swing.JFrame;

 

public class MoveSquareFrame extends JFrame

{

    public static final String UP = “UP”;

    public static final String DOWN = “DOWN”;

    

    public MoveSquareFrame () {

        SquareComponent sc = new SquareComponent ();

        // Put the component to draw the square

        add (sc);

        

        // Create a button to send the move up command

        JButton btnUp = new JButton (UP);

        // Set it an identifier, by which we can find out this button

        btnUp.setActionCommand (UP);

        // Set her listener – a component for drawing a square

        btnUp.addActionListener (sc);

        // Put the button to the top of the form – to the north

        add (btnUp, BorderLayout.NORTH);

        

        // Create a button to send a move command down.

        JButton btnDown = new JButton (DOWN);

        // Set it an identifier, by which we can find out this button

        btnDown.setActionCommand (DOWN);

        // Set her listener – a component for drawing a square

        btnDown.addActionListener (sc);

        // Put the button on the bottom of the form – to the south

        add (btnDown, BorderLayout.SOUTH);

        

        // Setting Coordinates

        setBounds (100, 100, 400, 400);

    }

}

If we read this code accurately, we can see that initially, we create a panel, then – buttons. While creating buttons, we name the panel (right in the constructor), then we set it the command’s name (in order to allow the panel to differentiate the event it was called by – button UP or DOWN). Calling the method addActionListener, we register our panel as an event listener. Finally, we set our button to either UP or DOWN. We have already discussed the layout topic in polymorphism chapter, so by default, the form uses BorderLayout – here the components are placed by the world’s sides: north, south, east, west, and centre. If you do not specify the direction, then the component will be placed in the centre. 

 

Let’s now take a look at our panel’s button code – it should not become too difficult for you, as we have used the method of rendering many times.

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

package edu.javacourse.move;

 

import java.awt.Graphics;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import javax.swing.JButton;

import javax.swing.JComponent;

 

// Our class is able to receive events from the button because implements the ActionListener interface

public class SquareComponent extends JComponent implements ActionListener

{

    // Define a constant for the size of the square

    private static final int SQUARE_SIZE = 30;

    // Define a constant for the step

    private static final int STEP = 10;

    // Define the fields for storing the current coordinates of the square

    private int x = 0;

    private int y = 0;

 

    @Override

    public void actionPerformed (ActionEvent e)

    {

        // The input parameter contains a link to the person who sent the message.

        // Get object by calling getSource ()

        // Using the instanceof word, we can verify that the object belongs

        // JButton class (or its descendant)

        if (e.getSource () instanceof JButton) {

            // Cast the object to the JButton type

            JButton btn = (JButton) e.getSource ();

            // Compare the command with the string UP

            if (MoveSquareFrame.UP.equals (btn.getActionCommand ())) {

                // Move upward with decreasing Y coordinate.

                y – = STEP;

            }

            // Compare the command with the string DOWN

            if (MoveSquareFrame.DOWN.equals (btn.getActionCommand ())) {

                // Move downwards to increase the Y coordinate

                y + = STEP;

            }

            // Redraw the component to refresh the screen.

            repaint ();

        }

    }

 

    @Override

    protected void paintComponent (Graphics g)

    {

        super.paintComponent (g);

        g.drawRect (x, y, SQUARE_SIZE, SQUARE_SIZE);

    }

}

A new thing for you will be actionPerformed method. This method is described in ActionListener interface.

 

Новинкой для нас будет метод actionPerformed. Это метод, который описан в интерфейсе ActionListener. And the button is completely indifferent to which class it is listening to – it may be another component, a class for recording files, for sending mail, and a sea of ​​all other classes. Just a contract is important – “I can listen to the button.” This allows at times to increase the flexibility in the design. Returning to the method – it takes as a parameter a special class / object that contains interesting information about the source of the event – in this case about the button. In our case, we are very interested in the parameter that we set – getActionCommand / setActionCommand. He will tell us which button is pressed. Once again pay attention to the pleasant opportunity to listen to events from both buttons.

 

And finally, the code to run our form:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

package edu.javacourse.move;

 

import javax.swing.JFrame;

 

public class MoveSquare

{

 

     public static void main (String [] args)

     {

         // Create a graphic window

         MoveSquareFrame msf = new MoveSquareFrame ();

         // Set the rule according to which the application will end when

         // close this form

         msf.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

         // Make the window visible

         msf.setVisible (true);

     }

}

I suggest you expand the example – add the LEFT and RIGHT buttons there and move the square to the sides. You can also make sure that the square “does not run away” off the screen.

 

Interfaces play a very important role in a large number of technologies, design patterns. We considered only the main ideas and forms of writing.


Leave a Comment