Created
July 15, 2015 21:29
-
-
Save webbower/91566df41f9788af63db to your computer and use it in GitHub Desktop.
PHP Classes that behave like classes from other languages
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Immutable (uses ->copy() to modify instances), properties are implicitly defined by constructor signature, getting an undefined property | |
* throws an exception, type check instance properties, iterate over properties?... | |
*/ | |
class ScalaCaseClass { | |
public function __construct() | |
{ | |
// Somehow make it very easy to have all the arguments in the signature map to publicly accessible (faux-)instance properties | |
// without having to define each one on the class, so that the constructor signature implicitly defines them | |
} | |
} | |
/** | |
* Can only get and set properties with getter/setter methods (that are magically defined using __call() for anything prefixed with “get” or “set”), | |
* faux-static typing uses annotations to type check setFoo() data, no static methods (not sure if that can be enforced)... | |
*/ | |
class JavaClass { | |
/** | |
* @var String | |
*/ | |
protected $myString; | |
public function __call($name, array $args) | |
{ | |
$action = substr($name, 0, 3); | |
if ($action !== ‘get’ && $action !== ’set') { | |
// Only works for getFoo()/setFoo() calls | |
// throw new BadMethodCallException(); | |
} | |
$propName = lcfirst(substr($name, 3)); | |
if(!property_exists($this, $propName)) { | |
// Only work for properties defined on this class | |
// throw new BadMethodCallException(); | |
} | |
switch($action) { | |
case ‘get’: return $this->$propName; break; | |
case ‘set’: $this->$propName = $args[0]; return; break; | |
default: // throw new BadMethodCallException(); break; | |
} | |
} | |
} | |
/** | |
* Can be modified at runtime (defining methods with a method and invoking them via __call(), constructor is ClassName.new(args)?, | |
* sadly you can’t modify the comparison operators unless you define methods to use instead (like $foo->eq($bar) or $foo->gt($bar)) | |
*/ | |
class RubyClass { | |
// Ruby-style constructor | |
public static function new(…$args) | |
{ | |
return new static(…$args); | |
} | |
protected function __construct(…$args) | |
{ | |
// Determine how Ruby constructor args are handled and how properties are defined and get/set | |
} | |
// Potentially split out comparison methods (below) into appropriate traits | |
/** | |
* Something like: | |
* public function eq(MyRubyClass $that) | |
* { | |
* return true; // somehow define the method of comparison | |
* } | |
*/ | |
// Equal | |
abstract public function eq(RubyClass $that); | |
// Not Equal | |
abstract public function ne(RubyClass $that); | |
// This is greater than that | |
abstract public function gt(RubyClass $that); | |
// This is less than that | |
abstract public function lt(RubyClass $that); | |
} | |
/** | |
* Takes any number of args in constructor and stores them internally possibly with type, access via numerical index, can simulate pattern matching? | |
* | |
*/ | |
class Tuple { | |
/** | |
* @var [Any] - Any number of data stored in numerically-indexed positions | |
*/ | |
public $data = []; | |
/** | |
* Special syntax to retrieve stored values by invoking the instance. | |
* $foo = new Tuple(‘foo’, 1, [‘hello’, ‘world’]); | |
* $bar = $foo(0); // ‘foo’ | |
* list($blah, $sneh) = $foo(0, 2)l // [‘foo’, [‘hello’, ‘world’]] | |
*/ | |
public function __invoke() | |
{ | |
return func_call_user_array([$this, ‘extract’], func_get_args()); | |
} | |
/** | |
* Extracts any stored values by their index and returns it in an array. Useful for using with list($foo, $bar, $baz) = $tuple->extract(0, 3, 4), | |
* or list($foo, $bar, $baz) = $tuple(0, 3, 4); | |
*/ | |
public function extract(array $indexes) | |
{ | |
return array_map($indexes, function($i) { | |
// Validate if the index exists first and throw if doesn't | |
return $this->data[$i]; | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment