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