<?php

$string 
= new vstring('Hello!');
$allcaps $string -> upper();
echo 
$allcaps -> get();

abstract class vscalar {
    
protected $value null;
    
final public function __construct($value null) {
        if (
$value !== null) {
            
$this -> set($value);
        }
        return 
true;
    }
    
abstract public function set($value);
    
abstract public function cast($value);
    
final public function get() {
        return 
$this -> value;
    }
}

abstract class vnum extends vscalar {
    
public function pow(num $vnum) {
        
$value pow($this -> get(), $vnum -> get());
        if (
is_int($value)) {
            return new 
vint($value);
        }
        else {
            return new 
vfloat($value);
        }
    }
    
public function abs() {
        
$value abs($this -> get());
        if (
is_int($value)) {
            return new 
vint($value);
        }
        else {
            return new 
vfloat($value);
        }
    }
}

final class vint extends vnum {
    
public function cast($value) {
        return 
$this -> set((int) $value);
    }
    
public function set($value) {
        if (
is_int($value)) {
            
$this -> value $value;
            return 
true;
        }
        else {
            
trigger_error('Invalid type'E_USER_WARNING);
        }
    }
}

final class vfloat extends vnum {
    
public function cast($value) {
        return 
$this -> set((float) $value);
    }
    
public function set($value) {
        if (
is_float($value)) {
            
$this -> value $value;
            return 
true;
        }
        else {
            
trigger_error('Invalid type'E_USER_WARNING);
        }
    }
}
final class vbool extends vscalar {
    
public function cast($value) {
        return 
$this -> set((bool) $value);
    }
    
public function set($value) {
        if (
is_bool($value)) {
            
$this -> value $value;
            return 
true;
        }
        else {
            
trigger_error('Invalid type'E_USER_WARNING);
        }
    }
}
final class vstring extends vscalar {
    
public function cast($value) {
        return 
$this -> set((string) $value);
    }
    
public function set($value) {
        if (
is_string($value)) {
            
$this -> value $value;
            return 
true;
        }
        else {
            
trigger_error('Invalid type'E_USER_WARNING);
        }
    }
    
public function sub(vint $posvint $length null) {
        if (
$length !== null) {
            return new 
vstring(substr($this -> get(), $pos -> get(), $length -> get()));
        }
        else {
            return new 
vstring(substr($this -> get(), $pos -> get()));
        }
    }
    
public function trim() {
        return new 
vstring(trim($this -> get()));
    }
    
public function reverse() {
        return new 
vstring(strrev($this -> get()));
    }
    
public function lower() {
        return new 
vstring(strtolower($this -> get()));
    }
    
public function upper() {
        return new 
vstring(strtoupper($this -> get()));
    }
    
public function ucfirst() {
        return new 
vstring(ucfirst($this -> get()));
    }
    
public function ucwords() {
        return new 
vstring(ucwords($this -> get()));
    }
    
public function replace(vstring $searchvstring $replace) {
        return new 
vstring(str_replace($search -> get(), $replace -> get()));
    }
}