Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Override

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

Let's take out this dummy code and get to the real stuff. Our database is created via this init_db script which you can execute from the command line whenever the mood strikes to make sure that your database is setup correctly. DING!

This creates a table with a team column. In here we can see that the first two team columns are team rebel and the second two are team empire. Since these two ships work differently, inside of our ShipLoader where we take that data and turn it into ship objects, I want to create ship objects for the empire and the rebels.

So let's do that, if ($shipData['team'] == 'rebel') which is the key inside the database. Then we'll have $ship = new RebelShip($shipData['name']);. Else, we'll throw in our normal ship line, which represents the Empire ship:

... lines 1 - 2
class ShipLoader
{
... lines 5 - 44
private function createShipFromData(array $shipData)
{
if ($shipData['team'] == 'rebel') {
$ship = new RebelShip($shipData['name']);
} else {
$ship = new Ship($shipData['name']);
}
... lines 52 - 57
return $ship;
}
... lines 60 - 76
}
... lines 78 - 79

Ok, this doesn't have anything to do with Object Oriented coding, it's just a nice example of a use case for multiple classes. We have a database table, and you can create different objects from that table. This is nice because we'll be able to have these two objects behave differently.

Overriding Class Methods

So far RebelShip and Ship have all the same stuff except for the one extra method I have on RebelShip that I'm not using.

If we go back and refresh, everything still works perfectly! Now, technically I'm fairly certain that two of these are RebelShip objects and two are Ship objects but we can't really tell right now. Clearly we need to add identifiers so we know who to cheer on.

To do this, start by adding public function getType() to our Ship and return a description, like 'Empire':

140 lines lib/Model/Ship.php
... lines 1 - 2
class Ship
{
... lines 5 - 134
public function getType()
{
return 'Empire';
}
}

Since we added that to Ship, we can call getType on both Ship and RebelShip.

Back in index.php towards the bottom add a new column for this called Type and echo $ship->getType();:

123 lines index.php
... lines 1 - 57
<table class="table table-hover">
... line 59
<thead>
<tr>
... lines 62 - 65
<th>Type</th>
... line 67
</tr>
</thead>
<tbody>
<?php foreach ($ships as $ship): ?>
<tr>
... lines 73 - 76
<td><?php echo $ship->getType(); ?></td>
... lines 78 - 84
</tr>
<?php endforeach; ?>
</tbody>
</table>
... lines 89 - 123

Back to the browser and refresh. Everything has joined to fight for the Empire! Which makes sense. Both ship classes use this same method.

Time for the next really powerful thing with inheritance. In addition to adding methods to a sub class like RebelShip you can override methods. Copy the getType from Ship and paste it into RebelShip and change what it returns to 'Rebel':

... lines 1 - 2
class RebelShip extends Ship
{
... lines 5 - 12
public function getType()
{
return 'Rebel';
}
... lines 17 - 21
}

RebelShip copies the entire blue print of Ship but it can replace any of those pieces. When we refresh now, we have two 'Rebel' ships in addition to our two 'Empire' ships. Excellent!

Overridden Methods are not Called

A key part of this is that the parent getType class is never called for all rebel ship objects it is completely replaced. If I echo 'Parent Function' inside of getType in the Ship class and refresh, we see our ugly text echoing for the Empire ships and not the Rebel ships. This is thanks to our parent function not being called in RebelShip.

On to more methods, another one on Ship is isFunctional which we setup to have a 30% chance of a ship being broken, which is what our cute cloud here indicates:

140 lines lib/Model/Ship.php
... lines 1 - 2
class Ship
{
... lines 5 - 16
public function __construct($name)
{
... lines 19 - 20
$this->underRepair = mt_rand(1, 100) < 30;
}
public function isFunctional()
{
return !$this->underRepair;
}
... lines 28 - 138
}

But, we all know that the Rebels are really scrappy and they don't have the luxury of letting their ships get broken. Even if they are kinda broken they still fly and make it work. Which is just one more reason why the rebels are awesome.

So I need to set this up so the Rebel ships are never showing as broken which we can do really easily by overriding isFunctional inside of RebelShip. Let's update this to return true; which will never show a rebel ship as broken:

... lines 1 - 2
class RebelShip extends Ship
{
... lines 5 - 17
public function isFunctional()
... line 19
return true;
}
}

When we refresh now the Rebel ships always have sunshine, and the Empire ships sometimes have adorable clouds.

By having two classes we are starting to shape the different behaviors and properties of each, while still keeping most things in common and not duplicated.

Leave a comment!

6
Login or Register to join the conversation
Dima Avatar

( ! ) Warning: require(Cache.php): failed to open stream: No such file or directory in index.php on line 3
Call Stack

for the first challenge of this video

Reply

Hey @Dima

Just checked this challenge and everything worked as expected, can you please re-check it, and probably give more context? Where do you see this error? Challenge browser or in message on page?

Cheers!

Reply
Default user avatar
Default user avatar Krzysztof | posted 5 years ago

Under the "Copy the getType from Ship
and paste it into RebelShip and change what it returns to 'Rebel':" you are showing wrong code (isFunctional function instead of getType).

Reply

Ah, you're right, done!

Nice catch, by the way, thank you!

Reply
Marc R. Avatar

Same thing after "Let's update this to return true" the code has no open curly brace

Reply

Hey Marc,

Hm, I'm not sure about it. It says:

So I need to set this up so the Rebel ships are never showing as broken which we can do really easily by overriding isFunctional inside of RebelShip. Let's update this to return true; which will never show a rebel ship as broken:

And then we show a code block for RebelShip that returns true in isFunctional(), see: https://symfonycasts.com/sc...

As for me it matches the video, am I wrong?

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

userVoice