Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changes between Version 8 and Version 9 of LanguageSpec2/Metamethods

Show
Ignore:
Author:
JarrettBillingsley (IP: 24.131.65.183)
Timestamp:
11/22/08 20:25:16 (11 years ago)
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • LanguageSpec2/Metamethods

    v8 v9  
    113113Again, tables have special behavior with this metamethod.  This is only called when assigning a key-value pair into a table which doesn't already exist in the table. 
    114114 
    115 Here is an example object showing how to use `opIndex` and `opIndexAssign` to emulate some container functionality. 
     115Here is an example class showing how to use `opIndex` and `opIndexAssign` to emulate some container functionality. 
    116116 
    117117{{{ 
    310310This method is just cool.  When you attempt to call a method on an object and that method either doesn't exist or isn't a function, you'll get an error.  However, sometimes you'd like to intercept this behavior, and that's what `opMethod` is for.  If an instance defines `opMethod` and you attempt to call a method which doesn't exist, `opMethod` will be called instead with the method's name as the first parameter and any other parameters following it.  `opMethod` is allowed to return any number of values.  In this way `opMethod` acts as a perfect replacement for the method that was supposed to have been called.   
    311311 
    312 Using the `opField`, `opFieldAssign`, and `opMethod` metamethods, we can now make a ''mock object'', which is an object which pretends like it's another object.  However since we are intercepting all the field accesses and method calls, we can do interesting things, like perform logging or convert method calls and field accesses into more interesting operations such as database accesses or remote procedure calls.  The mock object we create here is just a simple one which prints some debugging info upon each field access and method call. 
     312Using the `opField`, `opFieldAssign`, and `opMethod` metamethods, we can now make a ''mock class'', which is a class which pretends like it's another class.  However since we are intercepting all the field accesses and method calls, we can do interesting things, like perform logging or convert method calls and field accesses into more interesting operations such as database accesses or remote procedure calls.  The mock class we create here is just a simple one which prints some debugging info upon each field access and method call. 
    313313 
    314314{{{ 
    321321                :mObj = obj 
    322322 
     323        function opField(name: string) 
     324        { 
     325                writefln("Getting field {}", name) 
     326                return :mObj.(name) 
     327        } 
     328 
     329        function opFieldAssign(name: string, value) 
     330        { 
     331                writefln("Setting field {} to {}", name, value) 
     332                :mObj.(name) = value 
     333        } 
     334 
    323335        function opMethod(name: string, vararg) 
    324336        { 
    325337                writefln("Calling method {}", name) 
    326338                return :mObj.(name)(vararg) 
    327         } 
    328  
    329         function opField(name: string) 
    330         { 
    331                 writefln("Getting field {}", name) 
    332                 return :mObj.(name) 
    333         } 
    334  
    335         // You probably will have to always declare opFieldAssign as the last method in an object, 
    336         // only because otherwise it could interfere with the rest of the object's declaration. 
    337         function opFieldAssign(name: string, value) 
    338         { 
    339                 writefln("Setting field {} to {}", name, value) 
    340                 :mObj.(name) = value 
    341339        } 
    342340} 
    469467`opIn` is passed one value, which is the value on the left side of the "`in`" operator.  `opIn` is called on the value on the right side of the "`in`" operator.  `opIn` should return a bool; `true` if the value is in the object, and `false` otherwise.  Actually `opIn` can return any value, but they will all be converted to `bool`s (using the MiniD definition of truth and fallacy -- i.e. 0, 0.0, null are false..).  "`!in`" calls this metamethod, but it just inverts the truth value of the result. 
    470468 
    471 Extending the little Set object we made in the `opCatAssign` example, we can make the code a bit nicer-looking.  All we have to do is change the name of `contains` to `opIn`. 
     469Extending the little Set class we made in the `opCatAssign` example, we can make the code a bit nicer-looking.  All we have to do is change the name of `contains` to `opIn`. 
    472470 
    473471{{{ 
    541539== '''`bool opEquals(other)`''' == 
    542540 
    543 This metamethod is called when you use the equality or inequality operators (== or !=).  Equality is separated from comparison as for some types, ordering makes no sense while equality does (or vice versa); and often equality can be determined more efficiently than ordering.  This method should return `true` if `this` is equal to `other`, and `false` otherwise.  Let's just slightly modify the Value object
     541This metamethod is called when you use the equality or inequality operators (== or !=).  Equality is separated from comparison as for some types, ordering makes no sense while equality does (or vice versa); and often equality can be determined more efficiently than ordering.  This method should return `true` if `this` is equal to `other`, and `false` otherwise.  Let's just slightly modify the Value class
    544542 
    545543{{{