Bez kategorii
Operator overloading simulation for PHP.
PHP doesn’t support operator overloading. Cs2php is capable of simulating this feature while converting C# code to PHP.
Assume simple C# class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Lang.Php.Examples.BasicFeaturesExample { [Module("class.complex-number")] public class ComplexNumber { #region Constructors public ComplexNumber(double real, double imaginary) { this.Real = real; this.Imaginary = imaginary; } #endregion Constructors #region Static Methods // Public Methods [ScriptName("minus")] public static ComplexNumber operator -(ComplexNumber a, ComplexNumber b) { return new ComplexNumber(a.Real - b.Real, a.Imaginary - b.Imaginary); } [ScriptName("plus")] public static ComplexNumber operator +(ComplexNumber a, ComplexNumber b) { return new ComplexNumber(a.Real + b.Real, a.Imaginary + b.Imaginary); } public static implicit operator ComplexNumber(double x) { return new ComplexNumber(x, 0); } #endregion Static Methods #region Properties public double Imaginary { get; set; } public double Real { get; set; } #endregion Properties public static ComplexNumber operator *(ComplexNumber a, ComplexNumber b) { return new ComplexNumber(a.Real * b.Real - a.Imaginary * b.Imaginary, a.Real * b.Imaginary + a.Imaginary * b.Real); } public static ComplexNumber operator /(ComplexNumber a, ComplexNumber b) { var tmp = b.Real * b.Real + b.Imaginary * b.Imaginary; var re = a.Real * b.Real + a.Imaginary * b.Imaginary; var im = a.Imaginary * b.Real - a.Real * b.Imaginary; return new ComplexNumber(re / tmp, im / tmp); } } } |
Class represents complex number. Some operators like multiplication has been defined in it. Following code represents ComplexNumber
on PHP side.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<?php class ComplexNumber { public Imaginary; public Real; public function __construct($real, $imaginary) { $this->Real = $real; $this->Imaginary = $imaginary; } public static function minus($a, $b) { return new self($a->Real - $b->Real, $a->Imaginary - $b->Imaginary); } public static function plus($a, $b) { return new self($a->Real + $b->Real, $a->Imaginary + $b->Imaginary); } public static function op_Implicit($x) { return new self($x, 0); } public static function op_Multiply($a, $b) { return new self($a->Real * $b->Real - $a->Imaginary * $b->Imaginary, $a->Real * $b->Imaginary + $a->Imaginary * $b->Real); } public static function op_Division($a, $b) { $tmp = $b->Real * $b->Real + $b->Imaginary * $b->Imaginary; $re = $a->Real * $b->Real + $a->Imaginary * $b->Imaginary; $im = $a->Imaginary * $b->Real - $a->Real * $b->Imaginary; return new self($re / $tmp, $im / $tmp); } } ?> |
Operator methods has been converted exactly like normal static methods. Method name was taken from C# (like op_Multiply
) or from ScriptNameAttribute
(like minus method).
Let’s take a look at operators usage.
1 2 3 4 |
var a = new ComplexNumber(3, 2); ComplexNumber b = 12; var c = a * b; var d = a + b; |
And the same code in PHP
1 2 3 4 |
$a = new ComplexNumber(3, 2); $b = ComplexNumber::op_Implicit(12); $c = ComplexNumber::op_Multiply($a, $b); $d = ComplexNumber::plus($a, $b); |
As you can see implicit conversion of a real number to a complex number was converted to a static method ComplexNumber::op_Implicit
call. Moreover the addition and multiplication have been converted in similar way.
Of course CS2PHP can convert more complicated code, like this:
1 |
var e = (a + 17) * 3; |
1 |
$e = ComplexNumber::op_Multiply(ComplexNumber::plus($a, ComplexNumber::op_Implicit(17)), ComplexNumber::op_Implicit(3)); |
We can define more than one implementation for each operator. For example we can define two independent multiplication operators:
1 2 3 4 5 6 7 8 9 10 |
[ScriptName("mul1")] public static ComplexNumber operator *(ComplexNumber a, ComplexNumber b) { return new ComplexNumber(a.Real * b.Real - a.Imaginary * b.Imaginary, a.Real * b.Imaginary + a.Imaginary * b.Real); } [ScriptName("mul2")] public static ComplexNumber operator *(ComplexNumber a, double b) { return new ComplexNumber(a.Real * b, a.Imaginary * b); } |
We have to decorate at least one definition with ScriptNameAttribute
in order to specify different PHP names for both methods.
1 2 3 4 5 6 |
public static function mul1($a, $b) { return new self($a->Real * $b->Real - $a->Imaginary * $b->Imaginary, $a->Real * $b->Imaginary + $a->Imaginary * $b->Real); } public static function mul2($a, $b) { return new self($a->Real * $b, $a->Imaginary * $b); } |
And now we can test this solution using following code:
1 2 |
var m1 = new ComplexNumber(3, 2) * new ComplexNumber(4, 5); var m2 = new ComplexNumber(3, 2) * 5; |
1 2 |
$m1 = ComplexNumber::mul1(new ComplexNumber(3, 2), new ComplexNumber(4, 5)); $m2 = ComplexNumber::mul2(new ComplexNumber(3, 2), 5); |