Skip to content
Print

Scala for Java Refugees Part 3: Methods and Statics

21
Jan
2008

In this series, we’ve already laid the foundations for Scala’s syntax as well as gotten a feel for how some of its object-oriented constructs work.  We haven’t really looked at any of these subjects in-depth however.  Most of our effort has been focused on high-level, flash bang overviews that just get you tasting your way into the language.  This post will go into greater depth regarding method syntax, touch a bit on scopes and attempt to cover how static members work in Scala.  We will also touch on a few gotchas due to “missing” imperative instructions.

Methods Galore

Scala isn’t called a “functional language” just because it’s Turing complete.  Scala has a very powerful and flexible syntax as it relates to methods, both declaration and invocation.  We’ve already seen some basic samples:

class Person {
  def firstName() = {
    var back:String = ...   // read from a database
    back
  }
}

Fairly straightforward.  But this doesn’t really give you the full picture.  In Java for example, you can create methods with different visibilities, modifiers and (oddly enough) return types.  Does Scala support all of this flexibility?

The answer is a qualified “yes”.  Scala does allow for different visibilities on not just methods, but any members.  For example:

class Person {
  private var name = "Daniel Spiewak"
  val ssn = 1234567890    // public constant field
 
  def firstName() = splitName()(0)   // public method
 
  private def splitName() = name.split(" ")    // private method
 
  protected def guessAge() = {
    import Math._
    round(random * 20)
  }
}

At the risk of going on a tangent, it’s worth pointing out the (seemingly) out of place import statement within the guessAge() method.  I mentioned in the first post that Scala’s import is far more powerful than Java’s.  One of its many charms is imparting to the power to import into a specific scope.  The import statement within guessAge() is much like a Java static import statement which only provides access to the Math members within the guessAge() method.  So we couldn’t just make a call to round() from within the splitName() method.  Rubyists can think of it much like the include statement without all of the hassle (it’s not actually including, it’s importing and so eliminating the need for fully-qualified names).

Scala access modifiers are also quite a bit more powerful than Java’s.  For example, protected by default limits access to only subclasses, unlike Java which also allows access to other classes in the same package.  More importantly though, Scala allows the developer to more explicitly specify the scope of the access modifier.  This is accomplished using the modifier[package] notation.  For example:

package com.codecommit.mypackage
 
class MyClass {
  private[mypackage] def myMethod = "test"
}

In this example, myMethod is access-restricted to both the enclosing class and the enclosing package.  Essentially, this is how the Java-style package private modifier can be emulated using Scala.  The protected modifier also allows such visibility qualifiers.  The one restriction here is that the package specified must be an enclosing package.  In the above example, specifying private[com.codecommit.mypackage] is perfectly valid, but private[scala.collection.immutable] would not be correct.

So with the exception of package-private, visibilities work about the same in Scala as they do in Java, both in syntax and function.  Modifiers are really where things get interesting.  Scala has far fewer method modifiers than Java does, primarily because it doesn’t need so many.  For example, Scala supports the final modifier, but it doesn’t support abstract, native or synchronized:

abstract class Person {
  private var age = 0
 
  def firstName():String
  final def lastName() = "Spiewak"
 
  def incrementAge() = {
    synchronized {
      age += 1
    }
  }
 
  @native
  def hardDriveName():String
}

If we were in Java, we would write the above like this:

public abstract class Person {
    private int age = 0;
 
    public abstract String firstName();
 
    public final String lastName() {
        return "Spiewak";
    }
 
    public synchronized void incrementAge() {
        age += 1;
    }
 
    public native String hardDriveAge();
}

Yes, I know it’s more “Scala-esque” to use actors rather than synchronized(), but one step at a time.

You see how Scala keeps with its theme of making the common things concise?  Think about it, almost every method you declare is public, so why should you have to say so explicitly?  Likewise, it just makes sense that methods without a body should be implicitly abstract (unless they’re native).

One very important type-saving feature that you should see in the example above is that Scala doesn’t force you to declare the return type for your methods.  Once again the type inference mechanism can come into play and the return type will be inferred.  The exception to this is if the method can return at different points in the execution flow (so if it has an explicit return statement).  In this case, Scala forces you to declare the return type to ensure unambiguous behavior.

You should also notice that none of the Scala methods actually include a return statement.  This of course seems odd as judging by the Java translation, lastName() should return a String.  Well it turns out that Scala carries a useful shortcut for method returns: the last statement in an expression, be it a scope, a closure or a method becomes its return value.  This convention is also found in languages like Ruby and Haskell.  This example illustrates:

def name() = {
  val name = new StringBuilder("Daniel")
  name.append(" Spiewak");
  name.toString()
}
 
val s = name()
println(s)    // prints "Daniel Spiewak"

Again, in this example the return type of the method is inferred (as String).  We could just as easily have written the name() method as follows, it just would have been less concise.

def name():String = {
  val name = new StringBuilder("Daniel")
  name.append(" Spiewak");
  return name.toString()
}

This “returnless” form becomes extremely important when dealing with anonymous methods (closures).  Obviously you can’t return from a closure, you can only yield, however the principle is the same.  Since closures are often used to reduce code bulk and make certain algorithms more concise, it only makes sense that their return syntax would be as compact as possible:

val arr = Array(1, 2, 3, 4, 5)
val sum = arr.reduceLeft((a:Int, b:Int) => a + b)
 
println(sum)    // 15

In this example we’re passing an anonymous method to the reduceLeft() method within Array.  This method just calls its parameter function repeatedly for each value pair, passing them as the a and b parameters.  Here’s the key part though: our anonymous method adds the two parameters and yields the result back to reduceLeft().  Again, no return statement (or actually, as a closure it would be yield).  Also, we don’t explicitly specify the return type for the closure, it is inferred from our last (and only) statement.

Method Overriding

A very important concept in object-oriented programming is method overriding, where a subclass redefines a method declared in a superclass.  Java’s syntax looks like this:

public class Fruit {
    public int getWorth() {
        return 5;
    }
}
 
public class Apple extends Fruit {
    @Override
    public int getWorth() {
        return 1;
    }
}

Technically, the @Override annotation is optional, but it’s still good practice to use it.  This gives you the compile-time assurance that you actually are overriding a method from a superclass.  In principle, a method declared in a subclass overrides any method in the superclass declared with the exact same signature.  At first glance this seems great, less syntax right?  The problem is when you start dealing with APIs where you’re uncertain if you got the overriding method signature right.  You could just as easily overload the method rather than overriding it, leading to totally different functionality and sometimes hard-to-trace bugs.  This is where @Override comes in.

Scala actually has a bigger problem with method overriding than just signature verification: multiple inheritance.  Multiple inheritance is when one class inherits from more than one superclass.  C++ had this feature years ago, effectively demonstrating how horrible it can really be.  When Gosling laid out the initial spec for Java, multiple inheritance was one of the things specifically avoided.  This is good for simplicity, but it’s sometimes constraining on the power-end of life.  Interfaces are great and all, but sometimes they just don’t cut it.

The key to avoiding ambiguities in the inheritance hierarchy is explicitly stating that a method must override a superclass method.  If that method has the same signature as a superclass method but doesn’t override it, a compile error is thrown.  Add to that significant ordering in the extends/with clauses, and you get a workable multiple-inheritance scheme.  But I’m getting ahead of myself…

Here’s the Fruit example, translated into Scala:

class Fruit {
  def worth() = 5
}
 
class Apple extends Fruit {
  override def worth() = 1
}

Notice that in Scala, override is actually a keyword.  It is a mandatory method modifier for any method with a signature which conflicts with another method in a superclass.  Thus overriding in Scala isn’t implicit (as in Java, Ruby, C++, etc), but explicitly declared.  This little construct completely solves the problems associated with multiple inheritance in Scala.  We’ll get into traits and multiple inheritance in more detail in a future article.

Often times when you override a method, you need to call back to the superclass method.  A good example of this would be extending a Swing component:

class StrikeLabel(text:String) extends JLabel(text) {
  def this() = this("")
 
  override def paintComponent(g:Graphics):Unit = {
    super.paintComponent(g)
 
    g.setColor(Color.RED)
    g.drawLine(1, getHeight() / 2, getWidth() - 1, getHeight() / 2)
  }
}

This component is just a rack-standard JLabel with a red line drawn through its center.  Not a very useful component, but it demonstrates a pattern we see used a lot in Java: delegating to the superclass implementation.  We don’t want to actually implement all of the logic necessary to paint the text on the Graphics context with the appropriate font and such.  That work has already been done for us in JLabel.  Thus we ask JLabel to paint itself, then paint our StrikeLabel-specific logic on top.

As you see in the example, the syntax for making this superclass delegation is almost precisely the same as it is in Java.  Effectively, super is a special private value (much like this) which contains an internal instance of the superclass.  We can use the value just like super in Java to access methods and values directly on the superclass, bypassing our overriding.

That little bit of extra syntax in the extends clause is how you call to a superclass constructor.  In this case, we’re taking the text parameter passed to the default constructor of the StrikeLabel class and passing it on to the constructor in JLabel.  In Java you do the same thing like this:

public class StrikeLabel extends JLabel {
    public StrikeLabel(String text) {
        super(text);
    }
 
    public StrikeLabel() {
        this("");
    }
}

This may seem just a bit odd at first glance, but actually provides a nice syntactical way to ensure that the call to the super constructor is always the first statement in the constructor.  In Java, this is of course compile-checked, but there’s nothing intuitively obvious in the syntax preventing you from calling to the super constructor farther down in the implementation.  In Scala, calling the super constructor and calling a superclass method implementation are totally different operations, syntactically.  This leads to a more intuitive flow in understanding why one can be invoked arbitrarily and the other must be called prior to anything else.

Scala’s Sort-of Statics

Scala is a very interesting language in that it eschews many of the syntax constructs that developers from a Java background might find essential.  This ranges from little things like flexible constructor overloading, to more complex things like a complete lack of static member support.

So in Java, static members are just normal class members with a different modifier.  They are accessed outside of the context of a proper instance using the classname as a qualifier:

public class Utilities {
    public static final String APP_NAME = "Test App";
 
    public static void loadImages() {
        // ...
    }
 
    public static EntityManager createManager() {
        // ...
    }
}
 
System.out.println(Utilities.APP_NAME);
 
Utilities.loadImages();
EntityManager manager = Utilities.createManager();

Scala does support this type of syntax, but under the surface it is quite a bit different.  For one thing, you don’t use the static modifier.  Instead, you declare all of the “static” members within a special type of class which acts as an only-static container.  This type of class is called object.

object Utilities {
  val APP_NAME = "Test App"
 
  def loadImages() = {
    // ...
  }
 
  def createManager():EntityManager = {
    // ...
  }
}
 
println(Utilities.APP_NAME)
 
Utilities.loadImages()
val manager = Utilities.createManager()

The syntax to use these “statics” is the same, but things are quite a bit different in the implementation.  It turns out that object actually represents a singleton class.  Utilities is in fact both the classname and the value name to access this singleton instance.  Nothing in the example above is static, it just seems like it is due to the way the syntax works.  If we port the above class directly to Java, this is what it might look like:

public class Utilities {
    private static Utilities instance;
 
    public final String APP_NAME = "Test App";
 
    private Utilities() {}
 
    public void loadImages() { 
        // ...
    }
 
    public EntityManager createManager() {
        // ...
    }
 
    public static synchronized Utilities getInstance() {
        if (instance == null) {
            instance = new Utilities();
        }
 
        return instance;
    }
}
 
// ...

So Scala provides a special syntax which basically gives us a singleton for free, without all of the crazy syntax involved in declaring it.  This is a really elegant solution to the problems with proper statics.  Since Scala doesn’t actually have static members, we no longer have to worry about mixing scopes, access qualifiers, etc.  It all just works nicely.

But what about mixing static and instance members?  Java allows us to do this quite easily since static is a qualifier, but Scala requires “static” members to be declared in a special singleton class.  In Java, we can do this:

public class Person {
    public String getName() {
        return "Daniel";
    }
 
    public static Person createPerson() {
        return new Person();
    }
}

The solution in Scala is to declare both an object and a class of the same name, placing the “static” members in the object and the instance members in the class.  To be honest, this seems extremely strange to me and is really the only downside to Scala’s singleton syntax:

object Person {
  def createPerson() = new Person()
}
 
class Person {
  def name() = "Daniel"
}

The syntax for using this object/class combination is exactly the same as it would be in Java had we mixed static and instance members.  The Scala compiler is able to distinguish between references to Person the object and references to Person the class.  For example, the compiler knows that we can’t create a new instance of an object, since it’s a singleton.  Therefore we must be referring to the class Person in the createPerson() method.  Likewise, if a call was made to Person.createPerson(), the compiler is more than capable of deducing that it must be a reference to the object Person as there is no way to access a method directly upon a class.  It’s all perfectly logical and consistent, it just strikes the eye funny when you look at it.

Conclusion

And so ends our two part, whirlwind tour of Scala’s object-oriented constructs, methods and statics.  There are of course trivialities along the way which we haven’t covered, but those are easy enough to learn now that you have the basics.  The more interesting syntax is still to come though.  For one thing, we’ve barely scratched the surface of all of the things that you can do with methods.  They don’t call it a “functional” language for nothing!  But in keeping with our goal to represent the imperative side of the Scala language, we’ll save that for later.

In the next article, we’ll look at pattern matching and exception handling, two (surprisingly) related concepts.

Comments

  1. Keep this series going! I’m a long-time java developer who’s current work is mostly C#/.NET. I’ve been keeping tabs on F#, C# 3.0 including LINQ in the .Net world, and I’m fascinated by this new (to me) language, Scala. One question: I have an open source project written in Java that depends on Java 1.6. Can I write additions to it using Scala?

    Dale Monday, January 21, 2008 at 3:59 pm
  2. Certainly! Scala’s pretty flexible that way. I think the only limitation in terms of what Java dependencies you *can’t* extend with Scala would be anything pre-Java 5. If your project is already using Java 6, Scala should fit right in without a problem.

    Daniel Spiewak Monday, January 21, 2008 at 4:13 pm
  3. While it is not done in an exactly similar fashion to Java, Scala’s access modifiers are more flexible than Java’s because they have visibility qualifiers, that means you can have package protected too. Check the scala language reference under [Changes in Version 2.1.8] section titled: [Visibility Qualifier for protected]

    M. Ibrahim Monday, January 21, 2008 at 4:53 pm
  4. Well, I just quickscanned the article (will read it tomorrow) and noticed two errors. (as far as I know)
    1. protected in Scala is more restrictive than in Java (i.e. only subclasses may reference)
    2. package private would be defined as private[your.package.name], hence is possible

    Jan Monday, January 21, 2008 at 5:21 pm
  5. I’m really enjoying this series of articles. I was happy to read that you also find the “semantics-by-convention” of an object with the same name as a class to be a wart in Scala’s design. I don’t know if our minds are great, but they seem to think alike in that respect, at least.

    Again, thanks for the hard work you’re putting into making Scala accessible.

    Jonathan Feinberg Tuesday, January 22, 2008 at 7:35 am
  6. Good stuff.
    Two things:
    - It’s “Haskell”, not “Haskel”.
    - You could mention that “override” basically works like in C#.

    Wolfgang Tuesday, January 22, 2008 at 9:01 am
  7. @Wolfgang

    Actually, I’m not that familiar with the semantics of C#’s override keyword, so I didn’t want to delve into that end of it. Despite the (relatively) frequent references to Ruby and C++, I’m trying to keep most of the analogies accessible to the average Java developer.

    @M Ibrahim/Jan

    Darn, it seems I need to read the documentation a little more closely before posting these things… :-) I’ve corrected the article per your suggestions. Thanks for catching this!

    Daniel Spiewak Tuesday, January 22, 2008 at 11:34 am
  8. [One great thing about reading something that someone *else* has written is being able to tell them how *I* would have done it. Of course, I *didn't* do it, did I? Harumph... that shouldn't affect my entitlement to pontificate, should it?]

    In the discussion of visibilities, I would have also have mentioned private[this] and protected[this].

    I’d be tempted to add to the part at the end that an object with the same name as a class is called the “companion module” to the class, and a class with the same name as an object is called the “companion class” to the object, and that an object or class can access even the private members of its companion class or companion module.

    Also that since objects are actually class instances, a class can extend an object and vice versa. Methods in objects can be overridden just as easily as methods in classes can (something that isn’t true of static methods in Java).

    Doug Pardee Tuesday, January 22, 2008 at 8:25 pm
  9. Objects cannot act as superclasses since they’re not technically class types (well, I mean they are, but they aren’t). If you just try it in a scala shell, the results are interesting:

    scala> object TestSuper {
    | def testMethod = “Blah”
    | }
    defined module TestSuper

    scala> object TestSub extends TestSuper {
    | def testMethod = “BlahBlah”
    | }
    :4: error: not found: type TestSuper
    object TestSub extends TestSuper {
    ^

    scala> class TestSub extends TestSuper
    :4: error: not found: type TestSuper
    class TestSub extends TestSuper

    Wordpress is probably going to eat the formatting, but you get the picture.

    I thought about mentioning private[this] and protected[this], but decided against it. They’re important, but seem a bit over-detailed for this already too lengthy article. Besides, now that you’ve brought all this goodness up in a comment, why should I bother? :-)

    Daniel Spiewak Wednesday, January 23, 2008 at 11:07 am
  10. @article “The exception to this is if the method can return at different points in the execution flow (so if it has an explicit return statement). In this case, Scala forces you to declare the return type to ensure unambiguous behavior.”

    wish it would infer if all returns were the same. then fail if they aren’t. ya know?

    Raoul Duke Friday, February 1, 2008 at 3:22 pm
  11. I agree, that would be very nice. One solution of course is to write your code a bit more functionally and never use the *return* statement. In truth, return is really just a hold-over for the imperative side of Scala’s syntax. Carefully designed code will not *need* it.

    I wonder how long it’ll be before we start seeing “Return Considered Harmful” articles…

    Daniel Spiewak Friday, February 1, 2008 at 3:43 pm
  12. @return considered harmful

    ja, well, personally, as someone who has had to debug and maintain plenty of code, i think a single return point at the end of the function is the only way to go (barring exceptions).

    Raoul Duke Friday, February 1, 2008 at 4:05 pm
  13. @Raoul
    Is it that easy to determine if all return point values have the “same” type, and what type that would be, with implicits and variance (and overload/override)? (Honestly asking)
    OTOH, I consider that avoiding multiple return points IS programming to please some notion of ’structured’ or to simplify work for the machine and code readability usually suffers. There are such things as base cases, early fast returns for some (human) reason (and not an ‘optimizing’ one for the machine) … Maybe you miss postconditions?

    @Daniel
    I think it should also be mentioned that the companion object (or module) of a class should be defined in the same file (and that using companions in the interpreter is a PITA, for example you cannot use the person declarations in the interpreter unless you reorder, and visibility is not correctly solved: private members of the class are not visible to the companion object in the interpreter). I also have a sense that the object-module construct is a bit misleading and/or is missing some capabilities. Maybe, in it’s current form, the companion object should be a syntactic ‘coda’ to the class : class C { … } object { … } (with no name).

    javier Thursday, February 21, 2008 at 7:52 am
  14. I don’t know why you talk down the object / class syntax. I like it. It promotes a clean separation between the code of the “real” class and its service methods. From my experience the static service methods are usually defined in one place separated from the rest, and when that’s not the case then it’s usually a mess. So why not just have them in two separate adjacent blocks?

    Post-O-Matic Sunday, February 24, 2008 at 1:55 pm
  15. On the whole, I like the syntax. The only problem I have with it is it can be confusing at times if you aren’t used to it. Consider how case classes work in 2.7. Really, any time you need “static” members as well as dynamic, things become a bit weird.

    Daniel Spiewak Sunday, February 24, 2008 at 2:28 pm
  16. @Raoul:
    I’ve debugged a lot of code myself and I don’t remember ever having problems with multiple returns. I’ve already heart before people complaining about multiple returns but never understood what is so wrong about it. I don’t see e.g. anything wrong with this:

    String find( String[] args, String match) {
    if( args == null || args.length == 0 ) return “empty”;
    for(String s : args)
    if( s.equals(match) ) return “found”;
    return “not found”;
    }

    Christoph Tuesday, February 26, 2008 at 2:14 am
  17. Hey Daniel,

    your example

    package com.codecommit.mypackage

    class MyClass {
    private[com.codecommit.mypackage] def myMethod = “test”
    }

    is not working for me…The compiler complains about the first dot after “com”. However, if I only put “mypackage” for AccessQualifier, it works like charm.

    David Linsin Saturday, March 8, 2008 at 10:11 am
  18. Good catch! I was a little foggy on the syntax when I wrote the article, but I hadn’t remembered my error in the “package private” bit. Fixed!

    Daniel Spiewak Saturday, March 8, 2008 at 10:17 am
  19. FYI, Haskell does have a convention (in do blocks) where the last value is returned. However, this is *not* a shortcut: there is no way to return anything but the last value. Do blocks are monadic command sequences, so nothing but the last value makes sense anyway. There is a return function, but it’s not really comparable to the return of an imperative language.

    Sarah A Thursday, April 3, 2008 at 4:58 pm
  20. This series is, by far, the best intro to Scala I’ve come across. The content is great, but I think that I’ve gotten at least as much out of the comments.

    Thanks for putting in the time to respond, Daniel.

    Zack Tuesday, October 7, 2008 at 3:20 pm
  21. In Java you often have a static logger ….

    private static final Logger logger = Logger.getLogger(….the class .getName()… );

    Do you have any suggestions on how do you do this in Scala?

    Note: I’ve googled/heard (could be wrong) that static final ‘values’ … can become static fields … but Logger is not a value type.

    Cheers, Rob.

    PS: Nice work with your Scala articles – thanks for your efforts !!

    Rob Bygrave Thursday, March 26, 2009 at 5:43 pm
  22. I would do something like this:

    abstract class CanLog(name: String) {
      val logger = Logger getLogger name
    }

    Then, for each class for which you want to allow logging, declare the companion object as a subclass of CanLog. Thus, for some class DataBean, declare the class normally and then define the following additional snibblet:

    object DataBean extends CanLog("mypackage.DataBean")

    With this in place, you can safely get the static logger using “DataBean.logger” (without the quotes). That logger will indeed be static across the entire JVM just like a true Java static.

    Daniel Spiewak Thursday, March 26, 2009 at 6:20 pm
  23. Yes, I see that is an option – thanks… the downside that I see is that “object DataBean” generates a singleton class.

    … it just seems like overkill to me ( to require a singleton class for this ). Hmmm …

    Rob Bygrave Thursday, March 26, 2009 at 7:15 pm
  24. Hello,

    I have found your articles on Scala helpful. Thank you for writing them. However I have noticed an error in this post. You state that closures and anonymous methods are the same thing. The following sentence confused me:

    This “returnless” form becomes extremely important when dealing with anonymous methods (closures).

    In fact they are not the same. From Wikipedia:

    “The term closure is often mistakenly used to mean anonymous function. This is probably because most languages implementing anonymous functions allow them to form closures and programmers are usually introduced to both concepts at the same time. These are, however, distinct concepts.”

    See http://en.wikipedia.org/wiki/Closure_%28computer_science%29 for more.

    Niall O'Higgins Tuesday, March 23, 2010 at 5:47 pm
  25. Imagine you’d like to ‘port’ a your Java class onto OSGi environment.
    In a nutshell, what you have to do is:
    (1) extract the interface of your class
    (2) expose the interface so that clients will be able to call services you are providing
    (3) make the concrete implementation of your class (actually, your original class), implement the interface you’ve just exposed.

    If your Java class has ’statics’, you will be obliged to split your class in two:
    (a) one part which is similar to a Factory pattern, which contain non-static methods which were static methods in your original class and
    (b) another part which contains all non-static methods of your original class.

    In other words, you have to create the concepts of Scala class and the companion Scala object by hand, in Java. You have to do that when you are about to implement your application on top of OSGi, possibly breaking source compatibility with another platforms.

    So, we can see that Scala is very well suited to OSGi because it ‘forces’ developers to adopt a recommended strategy which is “get rid of statics” from day one.

    In particular, statics are ugly because they do not scale well and they jeopardize concurrent threads. If statics do not ’scale’ well, they cannot be part of Scala :)

    Scalability problems are certainly irrelevant with small applications but they are critical in the real world, when big and complex applications are needed in order to perform useful work, attending thousands or millions of requests a day.

    Scala was designed trying to address needs not only of professional developers but also addressing needs of huge, complex applications, running on enterprise grade environments.

    Thanks

    Richard Gomes

    Richard Gomes Wednesday, July 21, 2010 at 12:36 am
  26. Does it strike anyone else as especially perverse/strange that object-level methods go in “class” while class-level methods (in Java terms) go in “object”? It seems 100% backward to me.

    I like some of the ideas behind Scala but so far have found its syntax to be, shall we say, less than elegant.

    Ari Sunday, September 19, 2010 at 3:42 pm
  27. So, about logs, guys. You *really* create a companion object every time you need to log a statement? For a well-designed library it would mean that almost every class would have a companion singleton with `CanLog` mixed in.

    I guess I have to agree with Rob Bygrave about overkills.

    Boris Okunskiy Wednesday, February 15, 2012 at 1:41 am

Post a Comment

Comments are automatically formatted. Markup are either stripped or will cause large blocks of text to be eaten, depending on the phase of the moon. Code snippets should be wrapped in <pre>...</pre> tags. Indentation within pre tags will be preserved, and most instances of "<" and ">" will work without a problem.

Please note that first-time commenters are moderated, so don't panic if your comment doesn't appear immediately.

*
*