Introduction to Object-Oriented Design
What we’ve discussed?
We introduced notation for classes hierarchy and started thinking about different domains in the context of their structure and dependencies. We specified:
- interfaces (marked with I) define the behaviour of objects of some class by specifying its methods as only abstract methods
- abstract classes (marked with A or with cursive) define common behaviours (represented as methods) and properties (represented as fields) for some abstract group of objects. We’ve discussed the simplest Human abstract class that cannot exist by itself, but can contain common files like height and weight
- concrete classes that implement the abstract methods from their parent classes and can be instantiated
We’ve talked about the visibility of fields and methods in classes and introduced the notation of:
- + for public fields and methods that can be accessed in subclasses as well as by the external world
- # for protected fields and methods that can be accessed in the class in which they’re contained and its subclasses but cannot be accessed by the external world
- - for private fields and methods that can be accessed only in the class in which they’re contained
We started our designing tour with the classic example of Vehicles class structure that was finally similar to the structure of classes like
We have to note a few things that were discussed during the classes or on laboratory:
- we need to mark which classes/methods are abstract and which are concrete - on blackboard we use the notation of A letter but on diagrams it can be done with italic text
- if we want to have access to field from parent class in child class, we need to mark it not as private (-) but as protected (#)
- we need to provide the actual implementation for every abstract method in concrete classes (not marked with italic or A). That means that for every abstract method, we need to provide some actual implementation by writing this method as not abstract on the chain of classes between the first abstract declaration and the concrete class definition
- we pointed out that usually we would like to hide most of the backing fields from our implementation with private (-) modifier. However, sometimes we allow to access them in the child classes with protected (#) access modifier, when it may simplify our code.
Later we discussed the example of queue data structure that was modified a few times and was created during the labs in more general way. Let’s take a look how it can be presented (I added the LinkedQueue to show that not every queue need to be implemented with a backing array so maybe it’s not the best idea to put this array in Int queue)
If you have any question, feel free to contact me - I’ll try to share our conclusions here to simplify thinking of this kind of structure for other students.
We’ve also provided some implementation for LIFO queue methods - let’s see that they would be implemented at different levels, but some of them have general enough code, so they can be reused.
We managed to express only the abstract Graph interface (meaning the set of methods that the abstract class contains) and we pointed out that there are a few methods that can be expressed with the others. It’s really important that some of them are abstract, so have to have the implementation in child classes, but for some of them like dfs it’s enough to use the abstract methods to express its behaviour - we’ll start with this example on the next exercises to show how it can be done in practice.
I included on the diagram some possible concrete graph classes just to remind you about the mentioned restriction - every abstract method need to have an implementation in the concrete classes and me cannot forget about it 😉