In Shang, a class may have a common attribute validate which verifies that the state of the class member is valid. Whenever an attempt to modify a class member is made, the modification will be temporarily made and then validate is implicitly called. If it returns non-zero value, the validation is passed and the modification will take effect. Otherwise, the modification will be reversed.
Note that validate is called whenever an update of class member state is made. If x.a must equal to x.b in order for x to be valid, a simultaneous assignment (x.a, x.b) = (v, v) must be done in order to pass validation.
global.ellipse = class title = "ellipse"; public a = 1 in (0 to inf); public b = 5 in (0 to inf); auto longaxis = () -> max(parent.a, parent.b); auto shortaxis = () -> min(parent.a, parent.b); auto area = () -> pi * parent.a * parent.b; new = (a, b) -> (); end circle = class super = global.ellipse; title = "circle"; auto radius = () -> parent.a; auto longaxis = () -> parent.radius; auto shortaxis = () -> parent.radius; auto perimeter = () -> 2 * pi * parent.radius; common set_radius = r -> ((parent.a, parent.b) = (r, r)); common validate = () -> (parent.a == parent.b); new = (a, b) -> (); end u = circle.new(3, 3) u.a = 5; // won't workNote that without the validate function, u.a = 5 will change u to an ellipse with a = 5, b = 3.
oz 2009-12-22