| <?php |
| |
| # This file illustrates the cross language polymorphism using directors. |
| |
| require("example.php"); |
| |
| # CEO class, which overrides Employee::getPosition(). |
| |
| class CEO extends Manager { |
| function getPosition() { |
| return "CEO"; |
| } |
| } |
| |
| # Create an instance of our employee extension class, CEO. The calls to |
| # getName() and getPosition() are standard, the call to getTitle() uses |
| # the director wrappers to call CEO.getPosition. |
| |
| $e = new CEO("Alice"); |
| print $e->getName() . " is a " . $e->getPosition() . "\n"; |
| printf("Just call her \"%s\"\n", $e->getTitle()); |
| print "----------------------\n"; |
| |
| # Create a new EmployeeList instance. This class does not have a C++ |
| # director wrapper, but can be used freely with other classes that do. |
| |
| $list = new EmployeeList(); |
| |
| # EmployeeList owns its items, so we must surrender ownership of objects |
| # we add. This involves first clearing the ->disown member to tell the |
| # C++ director to start reference counting. |
| |
| $e->thisown = 0; |
| $list->addEmployee($e); |
| print "----------------------\n"; |
| |
| # Now we access the first four items in list (three are C++ objects that |
| # EmployeeList's constructor adds, the last is our CEO). The virtual |
| # methods of all these instances are treated the same. For items 0, 1, and |
| # 2, both all methods resolve in C++. For item 3, our CEO, getTitle calls |
| # getPosition which resolves in PHP. The call to getPosition is |
| # slightly different, however, from the e.getPosition() call above, since |
| # now the object reference has been "laundered" by passing through |
| # EmployeeList as an Employee*. Previously, PHP resolved the call |
| # immediately in CEO, but now PHP thinks the object is an instance of |
| # class Employee (actually EmployeePtr). So the call passes through the |
| # Employee proxy class and on to the C wrappers and C++ director, |
| # eventually ending up back at the CEO implementation of getPosition(). |
| # The call to getTitle() for item 3 runs the C++ Employee::getTitle() |
| # method, which in turn calls getPosition(). This virtual method call |
| # passes down through the C++ director class to the PHP implementation |
| # in CEO. All this routing takes place transparently. |
| |
| print "(position, title) for items 0-3:\n"; |
| |
| printf(" %s, \"%s\"\n", $list->get_item(0)->getPosition(), $list->get_item(0)->getTitle()); |
| printf(" %s, \"%s\"\n", $list->get_item(1)->getPosition(), $list->get_item(1)->getTitle()); |
| printf(" %s, \"%s\"\n", $list->get_item(2)->getPosition(), $list->get_item(2)->getTitle()); |
| printf(" %s, \"%s\"\n", $list->get_item(3)->getPosition(), $list->get_item(3)->getTitle()); |
| print "----------------------\n"; |
| |
| # Time to delete the EmployeeList, which will delete all the Employee* |
| # items it contains. The last item is our CEO, which gets destroyed as its |
| # reference count goes to zero. The PHP destructor runs, and is still |
| # able to call the getName() method since the underlying C++ object still |
| # exists. After this destructor runs the remaining C++ destructors run as |
| # usual to destroy the object. |
| |
| unset($list); |
| print "----------------------\n"; |
| |
| # All done. |
| |
| print "php exit\n"; |
| |
| ?> |