Static method and abstract class

Can some one tell me different scenarios where i have to use static method and abstract classes. I know the defination of them but want to know exactly when i can use them.

Relying on classes with static methods is similar to normal function calls but can allow better organsation, a common method of working pre namespaces if coming from a procedural backrgound was wrapping static methods in classes for possibly more targetted file based organisation allowing easier cross project organisation of common utility functions. Static methods are the function equivelent in OOP and without going into the internals of how PHP does things if they are housed in an instantiated class they exist outside in a singular shared reference unable to use the benefits of multiple states with $this.

http://www.phparch.com/2010/03/static-methods-vs-singletons-choose-neither/ might be worth a read, there is a few decades on this topic as it is a lamnguage design construct not inherit only to PHP. Actively searching for prior experience is the best way to learn as with any working method there is a cost to you later involved. I do nearly all TDD so the cost involved is to high to use static.

Abstract classes are incomplete implemtenations awaiting for the gaps to be filled in that define a common interface. Common examples appear in frameworks at the view/controller level to allow cohabitation with the rest of the framework after the finished implementation is done such as an external framework call to a common Execute method you have no control over. On the road to coding to interface( very abstract object communication ) over implementation the road of grasping things would look like this

function->static method->concrete finished class->abstract class->interface

With more abstractedness better smaller granular reusability can be harnessed and a greater level of working by rewiring versus rewriting can be attained. PHP tools can make this very hard to do though as they are usually quite a way behind the curve when it comes to helping you manage increasing levels of abstraction. As a by product this can promote a more line of site concrete development due to it is multiple times easier when limited with human memory constraints, though in TDD this can get very messy as lines of test per line of code goes way up to the point of untestable in an acceptable time frame and satisfactory coverage. That is another topic though but TDD helps with grasping the finer points of design and implementation. There are some more extreme examples such as using polymorphism to replace if statements and never using the new keyword outside a factory injecting it creations downwards etc and dependency injection containers to aid testability, rewirability and reusability.

A good excercise is to examine what needs to change when you are required to change something and whether you can write code in a way that always requires increasingly smaller changes as your learn more, if you do work for other people changes are hard to premedidate making it very challenging and the skill gained is seeing what is really conrete( checking for a resource existance but maybe not a specific type of resource such as a file on a hard disc, could be a backup tape ) and what isn’t such as user configurable vat rules so the calls to do these actions may be near each other but the tax calculatations and raw io calls make bad bed fellows to be near each other in the same class.

To get better understanding on this topic spend some time on dependency injection as that is tied to thinking in interface( method calls ) and ultitimately abstraction by swapping in different objects that may internally behave very differently.

It is quite a high level topic seemingly easy to grasp at the start but it takes a lot of refining and maybe arguments. A little example which may seem to have a lot of code but with it comes a lot of freedom with different tax calculations and different processing methods just by passing a differently configured TaxPaymentProcessor around, the effort was the filter var and comments as PHPStorm fills in on the abstract methods with stubs etc.


<?php
/**
 * A bit of a baby template method pattern, quite hard to to make up a really valid example without making up a bit more
 * implementation need
 */
abstract class TaxCalculator{
	public function __construct(){

	}


	/**
	 * handles shared implementation detail such as maybe verifying float in nature
	 * @param  float $taxableAmount
	 * @return void
	 * @throw Exception when amount is bad
	 */
	public function calculate( $taxableAmount ){
		if(!filter_var( $taxableAmount, FILTER_VALIDATE_INT | FILTER_VALIDATE_FLOAT  ) ){
			throw new Exception( $taxableAmount . ' is not a valid format to run calculation on.' );
		}

		return $this->runCalculation( $taxableAmount );

	}

	abstract protected function runCalculation( $taxableAmount );
}

/**
 * Class has been externally verified by auditors to verify it meets standards.
 * Get a bug in it and a it may be criminally negligent and the kittens may not get there Kitecat due to bankruptcy..
 * Unsafe to even eyeball unless you want to one day be accused of pulling a Richard Prior in superman 3
 * /office space move when things start truncing.
 */
class ReallyComplexTaxCalculatorThatOnlyAccountsWithALotOfTrainingCanFollow extends TaxCalculator{

	protected function runCalculation( $taxableAmount ) {
		return $taxableAmount * 100 / 125; // told you it was very complex
	}
}


class TinyTaxCalculator extends TaxCalculator{
	
	protected function runCalculation( $taxableAmount ) {
		return $taxableAmount * 100 / 101; // this is when floating errors or my bad maths start to kick in
	}
}


/**
 * Interface as a gateway could be https or a fixed pipe, transport methods can greatly differ so shared implementation
 * is maybe something to go to not but come from later with refactoring when the ground is more solid..
 */
interface PaymentStream{
	 function pay( $Amount );
}


class HttpsPaymentStream implements PaymentStream{

	public function __construct(){
		
	}
	
	public function pay( $Amount ) {
		return 'payed ' . $Amount . ' by https';
	}
}



class FixedPipePaymentStream implements PaymentStream {
	public function __construct(){
		
	}

	function pay( $Amount ) {
		return 'payed ' . $Amount . ' by fixed pipe';
	}
}


/**
 * By moving all configurable action out( well most ) we are left with a little shell to pass around to anything
 * that needs to this combined action but has no need to know the details of the action. 
 * but in real life one day this may go to an abstract class and then an interface.
 */
class TaxPaymentProcessor{
	private $taxCalculator;
	private $stream;
	public function __construct( TaxCalculator $taxCalculator, PaymentStream $stream ){
		$this->taxCalculator = $taxCalculator;
		$this->stream        = $stream;
	}


	public function processTax( $taxableAmount ){
		$calculatedTax = $this->taxCalculator->calculate( $taxableAmount );
		return $this->stream->pay( $calculatedTax );
	}
}


$httpsTaxPaymentProcessor = new TaxPaymentProcessor(
	  new ReallyComplexTaxCalculatorThatOnlyAccountsWithALotOfTrainingCanFollow(),
      new HttpsPaymentStream() );

echo $httpsTaxPaymentProcessor->processTax( 1000.1 ) . "\
";


$fixedPipeTaxPaymentProcessor = new TaxPaymentProcessor(
	  new TinyTaxCalculator(),
      new FixedPipePaymentStream() );

echo $fixedPipeTaxPaymentProcessor->processTax( 1000 ). "\
";

echo $fixedPipeTaxPaymentProcessor->processTax( 's' ). "\
";


Thanks a lot