Jump to content

What's the use of abstract classes/methods?


renatov
Go to solution Solved by .josh,

Recommended Posts

Hi guys, I'm studying PHP by myself (mainly using PHP manual, which lacks real world examples) and I have a question. As far as I understood, abstract classes can't be instantiated and the methods you specify as abstract must be defined by classes that extends the abstract class. Is that correct? If it is, I can't see the use of it. Are abstract classes important? What is it commonly used for in real world situations?

 

ps: is this subforum the right place to post questions like this?

Link to comment
Share on other sites

There are times when you want to create a number of subclasses that all inherit from the same base class, but insure that the base class can not be instantiated itself.  A simple example would be a zoo simulation where you decide that you want to have a factory class that can "make" new animals.  When your application needs to create a new lion, for example, you don't want to have to write the same code over and over, when you can instead have completely generic code that creates animals of any type.

 

Once an animal object is created, you will probably need to call some standard methods, and again if you based all your specific animal classes off an abstract animal class, your non-abstract methods can be called.  Imagine you need some code that Will store an animal name, birthdate, gender and location in a table. You may decide that for each animal class you'll have a seperate table  with the same name as the class.  So in this example, you will have a lion table in the database.

 

In your abstract animal class you might have:

//Animal class.
public function saveNew() {
    $table = get_class($this);
    $this->db->$table->insert(array('name' => $this->name, 'birthdate' => $this->birthdate, 'location' => $this->location, 'gender' => $this->gender));
}
 

Needless to say, you will not have an 'animal' table, so making the baseclass abstract provides some protection against issues with saveNew(). 

 

It also provides a standard set of methods the factory class can depend on, so it can feature code like:

// Animal Factory class
 
public function makeAnimal($type, $location) {
    $animal = new $type($location);
    $animal->setGender();
    $animal->setName();
    $animal->saveNew();
}

This code can be depended upon to work for any animal class that inherits from 'Animal'.  setName() is an example where you might want to have an abstract method, assuming that the rules for animal names would be different for each different type of animal.  The factory class will call setName(), but it is up to you to actually write function setName() when you create each individual class. 

 

SetGender()_ is another example, where you might lookup the relative ratio of male to female animals in a table where each row is named by class.  While you would have a row for lion, elephant and crocodile, you'll have no row for animal.

 

When trying to really dig into these ideas, you'll quickly find yourself gravitating towards "Object oriented design patterns".  The books on this subject will provide specific examples that should help you understand why the oop features in php were implemented in ways that the manual does not. 

Link to comment
Share on other sites

Thanks for your terrific explanation! I understand now the importance of abstract class with non abstract method, but when would an abstract method be better then an interface? I read that an interface acts pretty much like a bunch of abstract methods: you just define the signature and the implementing class will handle its implementation. A great example from the php manual comments is a "Database" interface. You define a necessary list of methods to handle database manipulation (listOrders(), addOrder(), removeOrder() etc) and then you tell a class to implement this interface, for example:

class MySqlDatabase implements Database {
    function listOrders() {... etc
}

$database = new MySqlDatabase();

foreach ($database->listOrders() as $order) { ...

Then, if you ever need to change your database, all you have to do is to implement another class with this interface and change the instantiation of $database, all the rest of the code could remain the same. This strategy seems a very good idea to me and maybe it could be done with abstract methods too, but would it be as practical as using interfaces? Abstract methods seems to me as if they were incomplete classes to be inherited for further development. When should abstract methods be used and when should we use infercaces?

Edited by renatov
Link to comment
Share on other sites

  • Solution

Okay so the point of abstract classes and interfaces is to guarantee certain methods/properties exist.  This isn't terribly useful when you're working on your own code by yourself.  But it does become useful when you're working with a bunch of other people and their own code.  

 

For example, if you create a CMS or some other script that allows for other people to develop plugins for it, they need to know how to integrate their plugin with your script.  And they need a level of guarantee that if you decide to change up your code, that their plugin isn't going to suddenly break, because some random $this->someFunction() no longer exists or whatever.  Or alternatively.. if you, as the creator of the script, provide functionality for people to create plugins for it, and so you setup your own script to depend on them doing something in their plugin, it's a level of guarantee that they will do it.

 

So essentially, abstract classes and interfaces are sort of a contract between two pieces of code, that says "I don't care what you do on your side of the fence, and you don't care what I do on my side of the fence, as long as we are in agreement that we communicate with each other via these set methods."  

 

Using gizmola's example with animals.. let's say you want to make a generic animal class and then child classes for different animal types. The animal class should define methods and properties that are applicable to all animal types.  And then you'd leave it up to the child classes to define stuff specific to them. So the point of making the ones a child class should define abstract, is to ensure that they actually define it, to protect against your own code breaking.  For example, properties like how old an animal is, its weight, etc.. should go in some child class.  But you may have a method in the parent class that makes use of those properties for something common among all animals.  But if the child class fails to define those properties, then the parent class code will break.  So if the parent class declares it as abstract, it forces the child class to define it.  

 

A more practical example.. 

 

Adobe Marketing Suite is a set of reporting tools for analysts and marketers. It's like Google Analytics, except GA is free and therefore has a lot of limitations. Adobe Marketing Suite is what the big boys use; it's enterprise level. Visitors go to a site, data about the visit is collected. Reports are rendered and analysts and marketers can see how many people go to their site and where they hang out on it and when/where they generally leave and then use that to try and figure out how to make their site better so that you buy their shit instead of walk out the door (sidenote: Yes, that really is what the tracking shit boils down to. So, the next time you go to a site and are trying to figure something out or buy something, but site is unclear, confusing, not working properly or w/e.. the best feedback you can give is to stop using addons that block or hide your visit activities on their site! Companies don't pay attention to emails people send to webmaster@mysite.com. They pay attention to their analytics reports.)

 

Anyways, so there's all that data in the reports and reporters want it to be classified, and they have their rules for how to classify it. So I have this script I wrote that well accept files with the raw data sent to my server from Adobe Marketing. The script then generates classification data based on the raw data vs. the defined business rules. The script then writes that to a file and sends it back to Adobe Marketing, and bam, reporters now have their data classified into whatever categories they want.  Well, the process is a bit more complicated than that, but that's the gist. 

 

So the way the script works (and again, I'm oversimplifying for the sake of example) is that I have a core class that does the generic stuff like receive the file, read through each row, generate new file and send back.  Then I have a child class to define the business rules. For example, one method isValidImportRow determines whether a given imported row should be parsed or skipped over.  Another method getClassifications generates the classification data for valid rows. Etc..  

 

But the main "engine", the loop that goes through each row of data is in the parent class.  So in the parent class, inside that loop, I call isValidImportRow and getClassifications.  So my parent class depends on that child class defining those methods and giving it something to work with.  This is where abstraction and interfaces come in handy.  In the parent class I can declare 

 

abstract private function isValidImportRow();
abstract private function getClassifications();
And this will force the child class to define those methods, so that the code in the parent class doesn't break when it calls them. So whenever some coder needs to create a new classification process with my script, they just need to define the child class that focuses only on translating the business rules to code. And if they don't define those methods, php yells at them.
Link to comment
Share on other sites

  • 2 weeks later...

I didn't have a chance to see the replies to this until today, but in regards to interfaces vs. abstract methods, they can be used relatively interchangeably in many cases. However, the big difference is that a class can implement multiple interfaces, whereas in PHP's single inheritance system, a subclass can only inherit from a single superclass.

 

You often see interfaces used in frameworks, where they expect people to write their own classes, that will then interact with the rest of the framework. Authentication is a good example, where you will often have a member class, often based on model base classes. In order to get the class to play with the generic authentication system, they'll provide an interface that the class needs to implement. This keeps everything decoupled and highly flexible in terms of how the framework user decides to store users --- be that in flat files, a database or a document store, while still insuring that it will be usable with the rest of the authentication system.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.