Here are key PHP OOP (Object-Oriented Programming) exercise questions with solutions:
Basic Class and Object Exercise:
// Create a simple bank account class
class BankAccount {
private $accountNumber;
private $balance;
public function __construct($accountNumber, $initialBalance = 0) {
$this->accountNumber = $accountNumber;
$this->balance = $initialBalance;
}
public function deposit($amount) {
if ($amount > 0) {
$this->balance += $amount;
return true;
}
return false;
}
public function withdraw($amount) {
if ($amount > 0 && $amount <= $this->balance) {
$this->balance -= $amount;
return true;
}
return false;
}
public function getBalance() {
return $this->balance;
}
}
// Usage
$account = new BankAccount("1234", 1000);
$account->deposit(500); // Balance: 1500
$account->withdraw(200); // Balance: 1300
Inheritance Exercise:
class Animal {
protected $name;
protected $age;
public function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
}
public function makeSound() {
return "Some sound";
}
}
class Dog extends Animal {
private $breed;
public function __construct($name, $age, $breed) {
parent::__construct($name, $age);
$this->breed = $breed;
}
public function makeSound() {
return "Woof!";
}
public function fetch() {
return "{$this->name} is fetching the ball!";
}
}
// Usage
$dog = new Dog("Rex", 3, "German Shepherd");
echo $dog->makeSound(); // Outputs: Woof!
echo $dog->fetch(); // Outputs: Rex is fetching the ball!
Interface Exercise:
interface Payable {
public function calculatePay(): float;
public function getPaymentDetails(): array;
}
class FullTimeEmployee implements Payable {
private $monthlySalary;
private $name;
public function __construct($name, $salary) {
$this->name = $name;
$this->monthlySalary = $salary;
}
public function calculatePay(): float {
return $this->monthlySalary;
}
public function getPaymentDetails(): array {
return [
'name' => $this->name,
'type' => 'Full Time',
'amount' => $this->calculatePay()
];
}
}
class ContractEmployee implements Payable {
private $hourlyRate;
private $hoursWorked;
private $name;
public function __construct($name, $rate, $hours) {
$this->name = $name;
$this->hourlyRate = $rate;
$this->hoursWorked = $hours;
}
public function calculatePay(): float {
return $this->hourlyRate * $this->hoursWorked;
}
public function getPaymentDetails(): array {
return [
'name' => $this->name,
'type' => 'Contract',
'amount' => $this->calculatePay()
];
}
}
Abstract Class Exercise:
abstract class Shape {
abstract public function calculateArea(): float;
abstract public function calculatePerimeter(): float;
}
class Circle extends Shape {
private $radius;
public function __construct($radius) {
$this->radius = $radius;
}
public function calculateArea(): float {
return pi() * pow($this->radius, 2);
}
public function calculatePerimeter(): float {
return 2 * pi() * $this->radius;
}
}
class Rectangle extends Shape {
private $width;
private $height;
public function __construct($width, $height) {
$this->width = $width;
$this->height = $height;
}
public function calculateArea(): float {
return $this->width * $this->height;
}
public function calculatePerimeter(): float {
return 2 * ($this->width + $this->height);
}
}
Static Methods and Properties Exercise:
class MathHelper {
private static $pi = 3.14159;
public static function circleArea($radius) {
return self::$pi * $radius * $radius;
}
public static function factorial($n) {
if ($n <= 1) return 1;
return $n * self::factorial($n - 1);
}
}
// Usage
echo MathHelper::circleArea(5); // Calculate circle area
echo MathHelper::factorial(5); // Calculate factorial
PHP static properties/methods and constants.
Key points about static:
Static members belong to the class itself, not instances
Access using ClassName:: syntax or self:: within the class
Static methods can only access other static properties/methods
Can't use $this in static methods
Useful for utilities and counter-like functionality
class Example {
// Static property
public static $counter = 0;
// Static method
public static function increment() {
self::$counter++;
return self::$counter;
}
// Accessing static property from instance method
public function getCount() {
return self::$counter; // Use self:: to access static members
}
}
// Using static members without creating an instance
Example::$counter = 5;
$count = Example::increment(); // Returns 6
// Can also access from instance, but not recommended
$obj = new Example();
$obj->getCount(); // Returns 6
Key points about constants:
Constants are immutable - value can't change
Class constants use const keyword
Global constants use define() or const (since PHP 5.3)
Constants are always public
Convention is to use UPPER_SNAKE_CASE
Use self:: to access within class
Good for configuration values and status codes
class Payment {
// Class constant
const STATUS_PENDING = 'pending';
const STATUS_COMPLETED = 'completed';
const TAX_RATE = 0.2;
// Using constants
public function calculateTax($amount) {
return $amount * self::TAX_RATE;
}
public function isPending() {
return $this->status === self::STATUS_PENDING;
}
}
// Accessing constants
echo Payment::STATUS_PENDING; // 'pending'
echo Payment::TAX_RATE; // 0.2
The main difference between static properties and constants:
Static properties can be modified at runtime
Constants are fixed and can't be changed
Constants are slightly more memory efficient
Use constants for fixed values, static for changeable class-level data
// Define global constants
define('MAX_USERS', 100);
const APP_VERSION = '1.0.0'; // Since PHP 5.3
echo MAX_USERS; // 100
echo APP_VERSION; // '1.0.0'
Create a class which allows the creation of objects only 3 times without external variables.
class LimitedClass {
private static $counter = 0;
public function __construct() {
if (self::$counter >= 3) {
throw new Exception("Cannot create more than 3 objects!");
}
self::$counter++;
}
// Optional: to see how many objects have been created
public static function getCount() {
return self::$counter;
}
}
// Usage example:
try {
$obj1 = new LimitedClass(); // Works
$obj2 = new LimitedClass(); // Works
$obj3 = new LimitedClass(); // Works
$obj4 = new LimitedClass(); // Throws Exception
} catch (Exception $e) {
echo $e->getMessage(); // "Cannot create more than 3 objects!"
}
// Check count
echo LimitedClass::getCount(); // Outputs: 3
Encapsulation Exercise:
class Student {
private $name;
private $grades = [];
public function setName($name) {
if (strlen($name) >= 2) {
$this->name = $name;
return true;
}
return false;
}
public function addGrade($grade) {
if ($grade >= 0 && $grade <= 100) {
$this->grades[] = $grade;
return true;
}
return false;
}
public function getAverageGrade() {
if (empty($this->grades)) {
return 0;
}
return array_sum($this->grades) / count($this->grades);
}
}
// Usage
$student = new Student();
$student->setName("John");
$student->addGrade(85);
$student->addGrade(90);
echo $student->getAverageGrade(); // Outputs: 87.5
These exercises cover:
Basic class creation and object instantiation
Inheritance
Interfaces
Abstract classes
Static methods and properties
Encapsulation
Method overriding
Constructor usage
Access modifiers
Key concepts demonstrated:
Encapsulation (private properties with public methods)
Inheritance (parent and child classes)
Polymorphism (method overriding)
Abstraction (interfaces and abstract classes)
Static members
Constructor usage
Type hinting
Return type declarations
Comments
Post a Comment