Ich muss Code von C++ nach Java portieren und in Java war ich noch nie wirklich fit. Heute bin ich dabei dann auch direkt auf ein Problem gestoßen. Es handelt sich um einen generischen Visitor, dem man den Typ einer Klasse mitgibt um zu bestimmen, ob der übergebene Base-Typ auch der angegebene Sub-Typ ist. Konkret geht es darum, mithilfe von Templates eine bestimmte Methode zu überladen. Das ist in C++ kein Thema, in Java leider schon.
Hier einmal der C++ Teil den ich portieren soll:
|
C-/C++-Quelltext
|
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
66
67
68
69
70
71
72
73
74
|
#include <iostream>
class BundleVisitor;
class Bundle
{
public:
virtual void accept(BundleVisitor&) = 0;
};
class AlphaBundle;
class BetaBundle;
class BundleVisitor
{
public:
virtual void visit(AlphaBundle*) = 0;
virtual void visit(BetaBundle*) = 0;
};
class AlphaBundle : public Bundle
{
public:
void accept(BundleVisitor& v)
{
v.visit(this);
}
};
class BetaBundle : public Bundle
{
public:
void accept(BundleVisitor& v)
{
v.visit(this);
}
};
class EmptyBundleVisitor : public BundleVisitor
{
public:
virtual void visit(AlphaBundle*) { }
virtual void visit(BetaBundle*) { }
};
template <typename T>
class BundleReveal : public EmptyBundleVisitor
{
private:
T* _bundle;
public:
void visit(T* bundle)
{
_bundle = bundle;
}
bool isValid()
{
return _bundle != nullptr;
}
};
int main()
{
// Demo
Bundle* bundle = new AlphaBundle();
BundleReveal<AlphaBundle> visitor;
bundle->accept(visitor);
std::cout << (visitor.isValid()) << std::endl;
delete bundle;
}
|
In Java bekomme ich ein ähnliches Äquivalent mit Generics aber leider nicht hin:
|
Quellcode
|
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
|
interface Bundle
{
void accept(BundleVisitor v);
}
interface BundleVisitor
{
void visit(AlphaBundle b);
void visit(BetaBundle b);
}
class AlphaBundle implements Bundle
{
public void accept(BundleVisitor v)
{
v.visit(this);
}
}
class BetaBundle implements Bundle
{
public void accept(BundleVisitor v)
{
v.visit(this);
}
}
class EmptyBundleVisitor implements BundleVisitor
{
public void visit(AlphaBundle b) { }
public void visit(BetaBundle b) { }
}
class BundleReveal<T extends Bundle> extends EmptyBundleVisitor
{
private T _bundle;
public void visit(T bundle)
{
_bundle = bundle;
}
public boolean isValid()
{
return _bundle != null;
}
}
public class MyClass
{
public static void main(String args[])
{
Bundle bundle = new AlphaBundle();
BundleReveal<AlphaBundle> visitor = new BundleReveal<>();
bundle.accept(visitor);
System.out.println(visitor.isValid());
}
}
|
Scheinbar sind die Generics nicht für eine solche Covariance ausgelegt. Hat jemand eine Idee, wie ich das Konstrukt dennoch lösen kann? Notfalls würde ich es einfach mit
instanceof und einen cast machen. Vermute mal, dass der C++ Code daher stammt, einen
dynamic_cast zu vermeiden, da es ja
instanceof in der Form nicht in C++ gibt/gab, aber kein Plan wirklich.