How to approach OOP interview questions
If you have problems with OOP technical interviews, here are some pointers on how to approach this kind of problems.
- outline (bottom up): write all the classes/components from small scope to big scope
- implementation (top down): write all method signatures from big scope to small scope.
- for the biggest class, start with the constructor, properties and then methods from the requirements(use cases, properties).
- for the smaller classes, requirements are from their upper classes’ implementation details + initial requirements(use cases, properties).
- changes (bottom up): if there’s any structural changes(deletion, addition, modification) on a particular part of the code, trace all places that used these changed part bottom up.
For example, designing an Excel, each cell has it’s own styles(font, size, color, etc), each cell can have different types of data(integer, string, boolean, etc), users can append or insert rows or columns
First step: outline(bottom up):
1 | class Cell<T> {} |
Second Step: implementation (top down):
start filling the classes from top down
Start with the Sheet’s constructor and some properties, on first thought, we just need an empty constructor
1 | public Sheet () { |
However, because we might need the dimension of the sheet upon constructing, either passed by user or by default. so we need a list of rows first, and the global column.
1 | List<Row> sheet = new ArrayList<Row>(); |
Notice, after we finished up the code above, we already added more requirements for the subclass Row
like new Row(column)
.
Then based on the requirements, we have appendRow
, insertRow
, appendColumn
, insertColumn
4 functions for sheet, let’s implement them.
1 | public void appendRow() { |
So based on code above, we can conclude the Cell’s constructor signature new Cell("")
, and also Row
’s method to add a cell row.add(new Cell("))
Now, let’s move to the next level of class, which is Row
.
First, let’s start with the constructor, based on the codes we added to Sheet
’s class, we already have our signature.
1 | List<Cell> row = new ArrayList<Cell>(); |
and we also know we need add
functions for Row
class too, one for appendRow
, another for insertRow
.
1 | public void add(Cell cell) { |
That’s it for now for Row
Lastly(for now), we need to complete our Cell
.
Last also start with the constructor, we already know the signature from the code above.
1 | T content; |
Because we want to add font, size, color, properties to each Cell
, let add these here
1 | String font = "Hei" ; |
That’s pretty much it if that’s all we need to do.
However, if we think a little deeper or more realistic, we need a way to update each cell’s data, so let’s do that too.
Let’s go top down again from Sheet.
1 | public void update(int row, int column, String content) { |
This, in turns, determines one function set
for Row
, so let’s do that.
1 | public void set(int col,Cell cell) { |
That’s it, if we want to update cells.
Third Step: Changes (bottom up)
In our current situation, we have font
, size
and bold
in each Cell
, however, what if we want to select a range of cells and apply the same style to these Cells. so that requires changes in our Cell
class, so let’s create a Style
class that’s shared across more than one Cell.
1 | class Cell<T> { |
Noticed that we added a style as a constructor param to Cell
, you don’t have to add it to the constructor if you want to create a setter(in java) or a property(in C#) or a variable (in PHP).
Now, because we changed the cell, we need to go bottom-up styles to fix all the places it sifts up to. Let’s keep a mental queue to add what we need to modify next (just like BFS*).
So in Row
’s constructors, we have two new
statements, let’s change that.
1 | public Row (int column) { |
We kept the previous constructor and overloaded a new constructor with a Style
object for the whole row
Let’s keep looking up the usage of Cell
while adding Row
to the queue to look up next.
We found appendColumn
, insertColumn
and all the update
s in Sheet
that use Cell
s constructor, let’s change that.
1 | // insert and append Col |
Notice that when we update, we keep the old style and assign it to the new cell created.
Also, this means we need to have a global style
in the sheet, and initialize the style in the constructor.
1 | Style style; |
After that, we are done with Cell
’s changes(bottom up), but we are done yet, remember, we added the Row
’s constructor to the queue, now let’s look at the places where Row
’s constructor is used.
We found the usages in Sheet
’s constructor, appendRow
and insertRow
.
For the Sheet
’s constructor, either we update it to sheet.add(new Row(column, style))
or just keep what it is if you don’t care about the extra same styles created for each Cell
. A better solution is sharing the same style, so let’s do that.
1 | public Sheet (int row, int column) { |
for appendRow
, and insertRow
, let’s change them.
1 | // insert and append Row |
Since this is the biggest class, they are not used anywhere, so we don’t need to add the changes to the queue(that’s not always the case though).
So the queue is empty now, so that means we are done with the effect by extracting styles to a Style
object.
Viola, that’s it.
If you want to read the complete code, here’s the link, I also added codes to apply styles to a range of cells over there.
Notes *Overall programming habit, BFS: don’t program too deep when there’s a thought, just go down 1 step down and just write the signature and keep writing.