MXMLC WTF (5)

Today I discovered yet another reason why properties aren’t such a good idea. When trying to declare the setter of a property internal and the getter public, mxmlc refuses to compile, complaining that there is an ambiguous reference.

This is the actual output of mxmlc (paths shortened for brevity):

[mxmlc] /.../ECSResponseParser.as(43): col: 10
              Error: Ambiguous reference to largeImageUrl.
[mxmlc]   item.largeImageUrl  = itemNode.LargeImage.URL.text();

The property is declared as follows (in the class ECSItem, in the same package):

private var _largeImageUrl : String;

internal function set largeImageUrl( newLargeImageUrl : String ) : void { _largeImageUrl = newLargeImageUrl; }

public function get largeImageUrl( ) : String { return _largeImageUrl; }

I don’t quite see how this is an ambiguous reference. Sure, I think I understand why mxmlc is confused – if the two classes had not been in the same package the statement would be illegal, and somewhere there mxmlc doesn’t really know how to apply the accessor modifier rules in this case. The ambiguity in question is whether there is a writable property or not, I belive.

There is no confusion on my part as to what the intention is: I want to make the property read-only outside the package because I don’t want, nor need, to return a mutable object. However, instances of the class in question are transfer objects (a.k.a value objects, data objects), so I wouldn’t mind it being simple to create a new instance and setting all the properties without having to send them all in the constructor or any other less elegant work-around.

I think the code is quite clear, but I also think that this is an example that shows why we probably shouldn’t have properties in the first place.

I find properties quite scary, actually. In Java or any other programming language without properties, you know that there will be no side-effects when you assign a value to something. It’s only methods that have side effects. When you add properties to the mix you have absolutely no idea. And being able to create read-only properties is weird – suddenly you have something that under some circumstances acts as a constant, but still can change.

Enough on properties. You may ask why I use them when I find them scary. My answer is that I belive them to be part of the ActionScript 3.0 and Flex programming style. To instead use Java-style getters and setters would be as inappropriate as using underscores instead of camel caps when naming methods. I can live with it.

The solution to this particular problem is to make the instance variables of ECSItem protected and then create a mutable subclass outside of the package scope of the ECSResponseParser class which lets that class create mutable instances while returning them typed as their immutable parent class.

MXMLC WTF is an ongoing series of short articles outlining weird things that the mxmlc compiler does.

4 Responses to “MXMLC WTF (5)”

  1. Spike Says:

    That’s an interesting issue, but there’s a much simples workaround for the specific example you give here:

    internal var _largeImageUrl : String;

    public function get largeImageUrl( ) : String { return _largeImageUrl; }

    As long as you don’t need to do anything in the setter other than set the internal value, you can just make the varible internal rather than private and dispense with the implicit setter completely.

    If you need to do something more complex in the setter, that’s a different story and you’d have to go with something like what you suggested.

  2. Theo Says:

    I did consider that solution, but in my opinion it falls in the category “other less elegant work-around[s]“.

    The reason for this is that you will couple your code to an instance variable, which cannot later be made into a property (without considerable ugliness).

    One of the only good aspects of properties is that you can start with instance variables and add logic as you go without breaking the interface, by referencing the instance variable directly you have side stepped that.

    Fair enough, this is such a simple case, and you may ask why bother with trying to adhere so strictly to encapsulation and whatnot? To be honest, I would have been perfectly happy with non-internal getters, or even public instance variables to solve this, but that’s not the point of this article.

    The point is to show that the mxmlc compiler cannot handle this situation, and that that can cause problems. In another example, there may not be a quick and dirty work-around.

    I’m sorry if I come off a little bit harsh, I do belive your intention to be good.

  3. Spike Says:

    If you’re concerned about a maintainable interface, why don’t you just create an internal scoped setter function that doesn’t use the implicit set keyword?

    That satisfies the maintainable interface requirement without needing to create an additional class. That would probably be a lot easier for anyone maintaining the code to understand without needing an explanation in the comments of both classes. A simple one line comment above the function should do it:

    // No implicit setter because of public/internal compiler scoping bug

    I appreciate that you’re just pointing out that the compiler is being stupid, and I agree with you. It just feels like your workaround is a little more cumbersome than it needs to be.

  4. Flora Says:

    Fair enough, this is such a simple case, and you may ask why bother with trying to adhere so strictly to encapsulation and whatnot? To be honest, I would have been perfectly happy with non-internal getters, or even public instance variables to solve this, but that’s not the point of this article.

Leave a Reply