InterviewQ: MyWorld Solution
Date: 2016-02-01 |
This post is part of my ongoing Interview Guide in which I log my journey to Software Engineering Wizardom.
Here’s the prompt, pulled directly from my January 2016 Interview Questions post:
MyWorld – OOP
Design a program (think OOP) that implements the following elements:
- World: Contains Countries, States, Cities, and Districts
- Country: Contains States, Cities, and Districts – has a name
- State: Contains Cities and Districts – has a name
- City: Contains a population – has a name
- District: Contains a population – has a name
For each of these entities (besides World), the name of the entity is declared in the first constructor argument and the entities within it are declared in the following arguments. You can assume that there won’t be any duplicate entities.
World should utilize a constructor that looks like this, don’t change it:
public world(Country… entitites) {
}
Here is an example of how the World will be populated through constructor calls:
([https://gist.github.com/SIRHAMY/2a0e8d175ddc14010f48](https://gist.github.com/SIRHAMY/2a0e8d175ddc14010f48))As you can see at the bottom of this gist, there are two calls you must implement in World:
- printPopulation(): This tallies up all of the populations inside the world. You can assume there won’t be any duplicate entities, so simply adding all the populations created will suffice.
- printWorld(): This prints out each of the entity names in the order in which they were declared. So yes, Countries, States, Cities, and Districts will be all jumbled together, but that’s by design. Just print out the names.
You can find my solution on GitHub. It might be useful to follow along while I walk you through it.
Basic design considerations:
- City and District must be able to hold their name as well as a population.
- State must be able to hold its name as well as multiple City and District elements.
- Country must be able to hold its name as well as multiple State, City, and District elements.
- World must be able to hold multiple Country elements and be able to successfully call printPopulation() and printWorld().
The first thing that sticks out is the weird ellipsis after Country in the World constructor. In Java, this means that you can handle a dynamic number of parameters of that type and that they’ll automatically be stored in an array, in this case called entities.
Because we know we aren’t supposed to modify the World constructor, we have to figure out a way that we can still access all of the declared State, City, and District elements from within the entities Country array. This leads us to our first big design decision:
- Each element must be able to hold the other elements for which the rules say it can contain.
For example, a State must be able to hold multiple City and District elements within it. By the same token, a Country must be able to hold multiple State, City, and District elements within it.
However, this leads us to another issue. All of the elements are being declared through the constructor, so how do we deal with a dynamic number of dynamic Class types in the parameters of each of our elements?
We might be able to get away with placing “Object… entities” in our constructor parameters, but this is dirty and will probably lead to casting errors down the road. How can we make this cleaner?
- Each element must be able to deal with a dynamic number of elements and types of elements passed in through its constructor.
The answer lies within one of our base OOP concepts: polymorphism. While the Object[] solution above also utilizes polymorphism, it’s very dirty. A much cleaner and more efficient way would be to create our own structure that allows us to be general in our constructor parameters, but also ensures each of our elements implements the methods we need.
Here we use an Interface which we’ll call Municipality. The methods in an Interface can’t be implemented within the Interface, they must be filled out inside the classes that implement it. This is perfect as we can now use “Municipality… elements” in the constructors for Country and State to hold elements that implement our new interface. By having each of our element types implement it, we can now pass them into the other element’s constructors cleanly.
On top of this, if we give our interface a getPopulation() and getString() method then all we have to do is modify these methods for each element level (Country, State, City, District) so that we achieve the correct result.
Try finishing the problem by yourself as an exercise.
If you get stuck, you can see how I implemented it below:
Want more like this?
The best / easiest way to support my work is by subscribing for future updates and sharing with your network.