stuff
[gitmo/Moose.git] / t / 031_mixin_example.t
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