Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can normal functions emulate OOP?

Can OOP programming be emulated with just normal functions? Like with using static variables and anonymous functions: http://php.net/manual/en/functions.anonymous.php

like image 576
Alex Avatar asked Mar 10 '26 20:03

Alex


2 Answers

Static variables are used to write procedural code, which at first glance looks like OOP.

OOP is a design pattern , which as nothing to do with which aspect of language you use. You would benefit a lot from reading following article: OOP vs Procedural Code. It explains for to write an object oriented code (even with only functions).

Also, you should be aware that functional programming is a completely different development paradigm. There are functional language which are made for this paradigm: JavaScript, Scala, Haskell, Erlang.

like image 141
tereško Avatar answered Mar 13 '26 08:03

tereško


I think the closest I can imagine quickly would be writing all of your functions to take their first argument as the data structure to operate on. Think of it like this:

OOP is essentially just coupling a known structure of data with appropriate behaviors.

So, if you are willing to trust yourself to only pass data structures that functions know how to work with, you could model it procedurally, with each "class" having two arrays in the global space, one for "instances", and one for "functions" (literally an array of callables, keyed on their name).

I wrote some code which defines "classes" as essentially a collection of methods, and those methods can essentially treat $self however they want (so long as they all know what to expect). This is a pretty cool idea (thanks for asking!). Note the use of anonymous functions, which could, in theory, be aggregated into a function-prototypes array and used on many different classes (i.e. just one "description" or "__toString" class, works on all classes).

edit: working code:

<?php

// The "Runtime" //
function makeObject($class, $constructorArgs) {
  global $classes;
  $constructorArgs = (array) $constructorArgs;
  $instance =  $classes[$class]['instances'][] = array();
  $instance['_class'] = $class;
  $instance = callMethod($instance, 'construct', $constructorArgs);
  return $instance;
}
function callMethod($instance, $method, $args = array()) {
  global $classes;
  return call_user_func_array($classes[$instance['_class']]['methods'][$method], array_merge(array($instance), $args));
}

// Class definition for "Person" //
$classes['Person'] = array();
$classes['Person']['methods'] = array();
$classes['Person']['methods']['construct'] = function($self, $name) {
    $self['name'] = $name;
    return $self;
};
$classes['Person']['methods']['sayHello'] = function($self) 
{
    echo "hello, my name is " . $self['name'] . "\n";
};
$classes['Person']['instances'] = array();


// Begin "Application" code.
// equivalent to: 
// $person = new Person("sally");
// $person->sayHello();

$person = makeObject('Person', "sally");
callMethod($person, "sayHello");

This can obviously be expanded in any number of fun and interesting ways. For instance, you can rework the structure of the "method" functions to also take a $parent argument, and allow children classes to call their parents, and allow callMethod() to lookup inherited methods when the child does not implement them. This is a lot of fun. Notice that only the last two lines are actually "application code"... the rest is equivalent to declarative "setup" code (analogous to class definitions) and the "runtime" functions.

like image 22
Chris Trahey Avatar answered Mar 13 '26 08:03

Chris Trahey