Commit | Line | Data |
505c6fac |
1 | #!/usr/bin/perl |
2 | |
3 | use strict; |
4 | use warnings; |
5 | |
6 | use Test::More tests => 1; |
7 | |
8 | BEGIN { |
9 | use_ok('Moose'); |
10 | } |
11 | |
12 | =pod |
13 | |
14 | This test demonstrates how simple it is to create Scala Style |
15 | Class Mixin Composition. Below is an example taken from the |
16 | Scala web site's example section, and trancoded to Class::MOP. |
17 | |
18 | NOTE: |
19 | We require SUPER for this test to handle the issue with SUPER:: |
20 | being determined at compile time. |
21 | |
22 | L<http://scala.epfl.ch/intro/mixin.html> |
23 | |
24 | A class can only be used as a mixin in the definition of another |
25 | class, if this other class extends a subclass of the superclass |
26 | of the mixin. Since ColoredPoint3D extends Point3D and Point3D |
27 | extends Point2D which is the superclass of ColoredPoint2D, the |
28 | code above is well-formed. |
29 | |
30 | class Point2D(xc: Int, yc: Int) { |
31 | val x = xc; |
32 | val y = yc; |
33 | override def toString() = "x = " + x + ", y = " + y; |
34 | } |
35 | |
36 | class ColoredPoint2D(u: Int, v: Int, c: String) extends Point2D(u, v) { |
37 | val color = c; |
38 | def setColor(newCol: String): Unit = color = newCol; |
39 | override def toString() = super.toString() + ", col = " + color; |
40 | } |
41 | |
42 | class Point3D(xc: Int, yc: Int, zc: Int) extends Point2D(xc, yc) { |
43 | val z = zc; |
44 | override def toString() = super.toString() + ", z = " + z; |
45 | } |
46 | |
47 | class ColoredPoint3D(xc: Int, yc: Int, zc: Int, col: String) |
48 | extends Point3D(xc, yc, zc) |
49 | with ColoredPoint2D(xc, yc, col); |
50 | |
51 | |
52 | Console.println(new ColoredPoint3D(1, 2, 3, "blue").toString()) |
53 | |
54 | "x = 1, y = 2, z = 3, col = blue" |
55 | |
56 | =cut |
57 | |
58 | { |
59 | package Point2D; |
60 | use metaclass; |
61 | |
62 | Point2D->meta->add_attribute('$x' => ( |
63 | accessor => 'x', |
64 | init_arg => 'x', |
65 | )); |
66 | |
67 | Point2D->meta->add_attribute('$y' => ( |
68 | accessor => 'y', |
69 | init_arg => 'y', |
70 | )); |
71 | |
72 | sub new { |
73 | my $class = shift; |
74 | $class->meta->new_object(@_); |
75 | } |
76 | |
77 | sub toString { |
78 | my $self = shift; |
79 | "x = " . $self->x . ", y = " . $self->y; |
80 | } |
81 | |
82 | package ColoredPoint2D; |
83 | our @ISA = ('Point2D'); |
84 | |
85 | ColoredPoint2D->meta->add_attribute('$color' => ( |
86 | accessor => 'color', |
87 | init_arg => 'color', |
88 | )); |
89 | |
90 | sub toString { |
91 | my $self = shift; |
92 | $self->SUPER() . ', col = ' . $self->color; |
93 | } |
94 | |
95 | package Point3D; |
96 | our @ISA = ('Point2D'); |
97 | |
98 | Point3D->meta->add_attribute('$z' => ( |
99 | accessor => 'z', |
100 | init_arg => 'z', |
101 | )); |
102 | |
103 | sub toString { |
104 | my $self = shift; |
105 | $self->SUPER() . ', z = ' . $self->z; |
106 | } |
107 | |
108 | package ColoredPoint3D; |
109 | our @ISA = ('Point3D'); |
110 | |
111 | ::with('ColoredPoint2D'); |
112 | |
113 | } |
114 | |
115 | my $colored_point_3d = ColoredPoint3D->new(x => 1, y => 2, z => 3, color => 'blue'); |
116 | isa_ok($colored_point_3d, 'ColoredPoint3D'); |
117 | isa_ok($colored_point_3d, 'Point3D'); |
118 | isa_ok($colored_point_3d, 'Point2D'); |
119 | |
120 | is($colored_point_3d->toString(), |
121 | 'x = 1, y = 2, z = 3, col = blue', |
122 | '... got the right toString method'); |
123 | |