using static narrow methods instead of %extended ones.

now it looks more natural and similar to the CORBA downcasting mechanism.


git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@5587 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Marcelo Matus 2003-12-23 10:10:04 +00:00
commit a152fd46a8
4 changed files with 56 additions and 37 deletions

View file

@ -18,6 +18,7 @@ public class virtual_poly_runme {
NDouble d = new NDouble(3.5); NDouble d = new NDouble(3.5);
NInt i = new NInt(2); NInt i = new NInt(2);
NInt j = virtual_poly.incr(i);
// //
// These two natural 'copy' forms fail, only java and csharp // These two natural 'copy' forms fail, only java and csharp
// because no polymorphic return types are supported. // because no polymorphic return types are supported.
@ -32,13 +33,16 @@ public class virtual_poly_runme {
NNumber dc = d.copy(); NNumber dc = d.copy();
NNumber ic = i.copy(); NNumber ic = i.copy();
// //
// The real problem is that there is no way to recover the // The real problem is that there is no way to recover the
// original NInt or NDouble objects, even when you try // original NInt or NDouble objects, even when you try to use the
// to use the plain and natural C++ dynamic_cast operations, // plain and natural C++ dynamic_cast operation, or the user
// since they fail: // downcasting mechanism:
// //
NDouble ddc = virtual_poly.NDouble_dynamic_cast(dc);
NInt dic = virtual_poly.NInt_dynamic_cast(ic); // don't work
NDouble ddc = NDouble.narrow(dc);
NInt dic = NInt.narrow(ic);
} }
} }

View file

@ -15,15 +15,20 @@ if d.get() != dc.get():
if i.get() != ic.get(): if i.get() != ic.get():
raise RuntimeError raise RuntimeError
virtual_poly.incr(ic)
if (i.get() + 1) != ic.get():
raise RuntimeError
# #
# here this dynamic_cast is not needed at all, # 'narrowing' also works
# but works fine anyway ('nnumber()' returns a NNumber).
# #
ddc = virtual_poly.NDouble_dynamic_cast(dc.nnumber()) ddc = virtual_poly.NDouble_narrow(d.nnumber())
if d.get() != ddc.get(): if d.get() != ddc.get():
raise RuntimeError raise RuntimeError
dic = virtual_poly.NInt_dynamic_cast(ic.nnumber()) dic = virtual_poly.NInt_narrow(i.nnumber())
if i.get() != dic.get(): if i.get() != dic.get():
raise RuntimeError raise RuntimeError

View file

@ -13,10 +13,10 @@ raise RuntimeError if d.get != dc.get
raise RuntimeError if i.get != ic.get raise RuntimeError if i.get != ic.get
# #
# dynamic cast working ('nnumber' returns a NNumber) # 'narrowing' working ('nnumber' returns a NNumber)
# #
ddc = Virtual_poly.NDouble_dynamic_cast(dc.nnumber) ddc = Virtual_poly::NDouble.narrow(dc.nnumber)
raise RuntimeError if d.get != ddc.get raise RuntimeError if d.get != ddc.get
dic = Virtual_poly.NInt_dynamic_cast(ic.nnumber) dic = Virtual_poly::NInt.narrow(ic.nnumber)
raise RuntimeError if i.get != dic.get raise RuntimeError if i.get != dic.get

View file

@ -1,11 +1,10 @@
%module(directors="1") virtual_poly %module(directors="1") virtual_poly
// //
// Check this example with directors wherever is possible. // Check this example with directors wherever is possible. Python and
// It seems to be a good test since it breaks ruby at least. // ruby work fine with and without directors. In theory, Java may
// python works fine with and without directors // start to work with directors, but this is not tested yet (my Java
// In theory, Java should starts working with directors, // installation is broken).
// but this is not tested yet (my Java installation is broken).
// //
//%feature("director"); //%feature("director");
@ -17,7 +16,7 @@
{ {
virtual ~NNumber() {}; virtual ~NNumber() {};
virtual NNumber* copy() const = 0; virtual NNumber* copy() const = 0;
NNumber* nnumber() NNumber* nnumber()
{ {
return this; return this;
@ -58,10 +57,18 @@
return new NInt(val); return new NInt(val);
} }
/* See below */
static NInt* narrow(NNumber* nn);
private: private:
int val; int val;
}; };
inline NInt& incr(NInt& i) {
i = i.get() + 1;
return i;
}
struct NDouble : NNumber struct NDouble : NNumber
{ {
NDouble(double v) : val(v) NDouble(double v) : val(v)
@ -78,6 +85,9 @@
return new NDouble(val); return new NDouble(val);
} }
/* See below */
static NDouble* narrow(NNumber* nn);
private: private:
double val; double val;
}; };
@ -95,32 +105,32 @@
of the language (strongly typed and 'by value' oriented), and of the language (strongly typed and 'by value' oriented), and
there is not much that can be done to work it around. there is not much that can be done to work it around.
However, to improve the situation, and to be able to recover the However, since the objects provide their own downcasting
original data types, we try adding 'dynamic_cast' interfaces in mechanim, the narrow methods similar to the CORBA mechanism,
the target language sides. This is a natural mechanism since is in theory you should be able to recover the original object
exactly the same you will do in the C++ side if is needed. types, just as you can do it in the C++ side or in other
languages.
*/ */
inline NInt* NInt_dynamic_cast(NNumber* n) { inline NInt* NInt::narrow(NNumber* n) {
// this is just a plain C++ dynamic_cast, but in theory the user
// could use whatever he wants.
return dynamic_cast<NInt*>(n); return dynamic_cast<NInt*>(n);
} }
inline NDouble* NDouble_dynamic_cast(NNumber* n) { inline NDouble* NDouble::narrow(NNumber* n) {
return dynamic_cast<NDouble*>(n); return dynamic_cast<NDouble*>(n);
} }
/* /*
but they don't work either in Java (see the but the narrow methods don't work either in Java (see the
java/virtual_poly_runme.java file), because of the current way java/virtual_poly_runme.java file), because of the current way
polymorphic types are wrapped. Using the wrapping method employed polymorphic classes are wrapped, the user cannot downcast the
with directors (which are also polymorphic types) should allows Java temporary object when the C++ class (and associated Java
to use the C++ dynamic_cast and recover the original types at the class) is a base class in a class hierarchy.
Java side. And to do that, it is necessary to identify which
classes are polymorphic (the "polymorphic" attribute does that)
and apply the proper wrapping mechanism.
The dynamic_cast interfaces added to this module, currently work The 'narrow' methods work currently fine in languages like
great in languages like python, but in there the polymorphic python, but in there the polymorphic return type also works, so,
return type also works, so, you are not forced to use them as a you are not forced to use them everytime (see the
fixing mechanism (see the python/virtual_poly_runme.py file). python/virtual_poly_runme.py file).
*/ */
%} %}