Post on 22-Jan-2018
Inheritance: Vertical or Horizontal?
Mark Niebergallhttps://joind.in/talk/77415
About Mark Niebergall• PHP since 2005 • Masters degree in MIS • Senior Software Engineer • Drug screening project • UPHPU President • CSSLP, SSCP Certified and SME • Drones, fishing, skiing, father, husband
About Mark Niebergall• Twitter @mbniebergall • phpug.slack.com • phpchat.slack.com • phpcommunity.slack.com • utos.slack.com
Inheritance: Vertical or Horizontal?
Inheritance: Vertical or Horizontal?
• Objective
- Solid understanding of how inheritance works in PHP
- Know when and how to use inheritance in PHP
- Able to apply material to current projects
Inheritance: Vertical or Horizontal?
• The Problem
• Vertical inheritance
• Horizontal inheritance
• Applied use
• Considerations
The Problem
The Problem• Copy and paste
The Problem• Procedural code
- Simple
- Efficient
The Problem• Procedural code
- Lacks organization
- Difficult to scale
The Problem• Functions
- Reusable
- Some organization
- No grouping
The Problem• Concrete Class
- Basic code organization with classes
- Concrete class can be instantiated
The Problem• Concrete Class
- Properties
- Constants
- Methods
- Magic methods
The Problem• Concrete Class
- class X { const SOME_THING = ‘Thing’; protected $flag = true; private function secretStuff() {…} public function doSomething() {…}}
The Problem• Concrete Class
- Problems by themselves
‣ Code reuse, duplication
‣ Code enforcement
‣ Code organization
The Problem• Concrete Class
- Problems by themselves
‣ Classes can become bloated
‣ No separation of services
‣ Complicated code
The Problem• Concrete Class
- Problems by themselves
‣ Hard to debug
‣ Testability goes down
The Problem• Concrete Class
- Some problems solved with Dependency Injection (DI)
‣ public function __construct(Dependency $d) { $this->dependency = $d;}public function setThing(Thing $thing) { $this->thing = $thing;}public function __set($key, $value) { if ($value instanceof Thing) {$this->thing = $value;}}
The Problem• Concrete Class
- Problems solved with inheritance
The Problem• Concrete Class
- Composition over Inheritance
- Inheritance over Composition
Vertical Inheritance
Vertical Inheritance• Family
- Olsen line
‣ Stature
‣ Stubbornness
- Niebergall
‣ Engineering
Vertical Inheritance• Service provider
- Education
‣ University
- Utilities
‣ Garbage collection
Vertical Inheritance• Animal
- Pet
‣ Dog
• German Shepard
‣ Cat
• Short-hair
Vertical Inheritance• Abstract
• Interface
Vertical Inheritance• Abstract
- X is a Y
Vertical Inheritance• Abstract
- X is a Y
‣ Mark is a Niebergall
‣ Garbage Collection is a Utility
‣ Cat is a Pet
Vertical Inheritance• Abstract
- X is a Y
‣ Pet is an Animal
• Cat is a Pet
• Short-hair is a Cat
Vertical Inheritance• Abstract
- abstract class Animal {…}
‣ abstract class Pet extends Animal {…}
• abstract class Cat extends Pet {…}
• class class ShortHair extends Cat {…}
Vertical Inheritance• Abstract
- abstract class Animal { abstract public function breathe(Lungs $lungs) : Lungs; private function beAlive() : Animal {…}}abstract class Cat { public function breathe(Lungs $lungs) : Lungs {…} final protected function purr() {…}}
Vertical Inheritance• Abstract
- class ShortHair { public function takeNap() { $this->goToSleep(); } public function getPetted() { $this->purr(); }}
Vertical Inheritance• Abstract
- Extend only one class at a time
- Can have multiple levels of inheritance
- Can not instantiate abstract
Vertical Inheritance• Abstract
- Abstract functions must be implemented
- Signatures must match
Vertical Inheritance• Abstract
- Benefits
‣ Reduce code duplication
‣ Code organization
‣ Logical flow
Vertical Inheritance• Abstract
- Push code up the vertical inheritance chain as far as it logically makes sense
Vertical Inheritance• Abstract
- Questions?
Vertical Inheritance• Interface
Vertical Inheritance• Interface
- interface X { const SOME_VALUE = 123; public function processThing(Thing $thing) : Thing;}
Vertical Inheritance• Interface
- Object interface
Vertical Inheritance• Interface
- Connect two things together
‣ User interface
‣ Driver and vehicle
‣ Controller
Vertical Inheritance• Interface
- Contract defining what needs to happen but not how
- Contract between concept and implementation
Vertical Inheritance• Interface
- Define interaction requirements
- Leaves implementation to be handled in classes
- Can not be instantiated
Vertical Inheritance• Interface
- Class can implement multiple interfaces
- Can be used with abstract and class
- Can not be used with a trait
‣ RFC in discussion about that
Vertical Inheritance• Interface
- interface X {…}
- class A implements X {…}
- abstract class Z implements V, W, X {…}
Vertical Inheritance• Interface
- Interface method signatures are defined
- No method content
- Method signature must match when implemented
- Methods must be implemented
- Interface can extend one or many interfaces
Vertical Inheritance• Interface
- All methods must be public
- Properties are not allowed
- Can have public constants
Vertical Inheritance• Interface
- Light from different sources
- interface LightInterface { const LIGHT_SPEED = 299792458; public function shine(Energy $energy) : Light; public function travel(float $x, float $y, float $z);}
Vertical Inheritance• Interface
- Laptop computer
‣ USB
‣ Video and audio output
‣ Card reader
Vertical Inheritance• Interface
- interface Power { public function receivePower(Volt $v, Current $i);}interface Usb extends Power{ public function transferData(Data $data);}interface Hdmi { public function transmitVideo(Video $video);}abstract class Laptop implements Usb, Hdmi {…}
Vertical Inheritance• Interface
- Underwater pets
- Auditing
- Authentication methods
- Request and response
‣ Middleware
Vertical Inheritance• Interface
- Questions?
Vertical Inheritance
Horizontal Inheritance
Horizontal Inheritance• Personal characteristics
- Hair color
- Personality
Horizontal Inheritance• Underwater creature
- Fish
- Mammal
- Reptile
Horizontal Inheritance• Trait
Horizontal Inheritance• Trait
- trait M { protected $thing; public function doThing(Thing $thing) : Thing {…}}class X { use M; protected function something(Thing $thing) : Thing { return $this->doThing($this->thing($thing); }}
Horizontal Inheritance• Trait
- Promotes code reuse
- Unrestricted by inheritance hierarchies
- Available since PHP 5.4.0
Horizontal Inheritance• Trait
- Pull in grouped functionality
- Multiple inheritance horizontally
- Similar to a concrete class but cannot be instantiated
Horizontal Inheritance• Trait
- “Aware” of a concept
‣ ContainerAware
‣ AuditAware
‣ AdapterAware
Horizontal Inheritance• Trait
- Can be used alongside abstracts and interfaces in a class
- Class can use multiple traits
- Used in abstract class or concrete class
- Can have properties and methods
Horizontal Inheritance• Trait
- Can not be instantiated
- Can not implement an interface
- Can not extend a class
Horizontal Inheritance• Trait
- Methods and properties in trait(s) become available to class
- Traits can not have class constants
Horizontal Inheritance• Trait
- Order of precedence
‣ Class and trait method naming collisions
• Current class
• Trait
• Parent class
Horizontal Inheritance• Trait
- abstract class TheBase { public function hello() { echo ‘Hello from the base.’; }}trait TheTrait { public function hello() { echo ‘Hello from the trait.’; }}class TheClass extends TheBase { use TheTrait; public function hello() { echo ‘Hello from the class.’; }}
Horizontal Inheritance• Trait
- trait TheTrait { public function hello() { echo ‘Hello from the trait.’; }}class TheClass extends TheBase { use TheTrait { TheTrait::hello as helloTrait; }; public function hello() { echo ‘Hello from the class.’; } public function helloBase() { parent::hello(); }}
Horizontal Inheritance• Trait
- Naming conflicts must be resolved
‣ Fatal error if not
Horizontal Inheritance• Trait
- ‘insteadof’ to use just one
- ‘as’ to alias and allow using more than one
Horizontal Inheritance• Trait
- class Thing { use TraitA, TraitB { TraitA::doThing insteadof TraitB; TraitA::doOtherThing as doOtherThingA; TraitB::doOtherThing as doOtherThingB; }}$thing->doThing();$thing->doOtherThingA();$thing->doOtherThingB();
Horizontal Inheritance• Trait
- Can change visibility modifier
‣ use Trait { methodName as protected; }
‣ class Thing { use Trait { Trait::doThing as public; }}$thing->doThing();
Horizontal Inheritance• Trait
- Traits can have properties
- Class properties must match visibility and initial value if same name
‣ trait X { public $something = ‘something’;}class Z { use X; public $something = ‘something’;}
Horizontal Inheritance• Trait
- Traits can use other traits
‣ trait Thing { use ThingA, ThingB;}
Horizontal Inheritance• Trait
- Traits can have abstract methods
‣ trait Thing { abstract protected function doSomething();}class X { use Thing; protected function doSomething() { echo ‘doing something’; }}
Horizontal Inheritance• Trait
- Traits can have static methods
‣ trait Thing { public static function anotherThing();}class X { use Thing; }X::anotherThing();
Horizontal Inheritance• Trait
- Recap
‣ Overcome multiple inheritance problem
‣ Horizontal inheritance
Horizontal Inheritance
Applied Use
Applied Use• Vertical or Horizontal inheritance?
- Vertical: abstract, interface
- Horizontal: trait
Applied Use• Vertical or Horizontal inheritance?
- Vertical is heavily used
- Most concrete classes extend an abstract in projects
Applied Use• Vertical or Horizontal inheritance?
- My experience
‣ Most use vertical
‣ Few use horizontal
Applied Use• Vertical or Horizontal inheritance?
- My experience with concrete classes
‣ Most extend an abstract
‣ Some implement an interface
‣ Few use trait
Considerations
Considerations• Open discussion
Considerations• Why need for abstracts, interfaces, and traits
Considerations• Benefits of using combinations of abstracts, interfaces, and
traits
Considerations• Traits vs Dependency Injection
Considerations• Role of Dependency Injection
Considerations• Code complexity
- How far to take abstraction
- Readability
- Code consolidation
Considerations• Code testability
- Unit tests
- Testing abstract instead of concrete implementation
Considerations• Evaluating current projects
- Static code analysis
- Leverage inheritance
Sources• https://en.wikipedia.org/wiki/Convair_B-36_Peacemaker
• http://www.boeing.com/resources/boeingdotcom/commercial/737ng/assets/images/marquee.jpg
• https://www.gannett-cdn.com
• http://pop.h-cdn.co/assets/15/20/1600x800/landscape-1431629947-marty-delorean.jpg
• http://www.sbs.com.au/movies/sites/sbs.com.au.film/files/styles/full/public/Dynamite_704.jpg?itok=_XPK3CbV&mtime=1404453609
• http://latimesblogs.latimes.com/.a/6a00d8341c630a53ef01310f8dd9fe970c-pi
• https://i.pinimg.com/474x/f8/32/b4/f832b4c3b92cc4ccd19a285f68a4197a--merlin-olsen-little-houses.jpg
• php.net