Aesphere
Aesphere

Reputation: 604

AS3 - Retype/Cast an inherited variable permanently in a subclass?

Possibly bad practice but I'm not well versed in software design anyway (I'm sure this question would have been asked before but I can't seem to find the right terminology)...Anyhow, it's just another curiosity of mine I'd like to have answered.

So I have worked in a way where I type a base class variable to type Object or Sprite or something similar so that in my subclasses, I can instantiate my custom classes into them and store it. And when I access it, I just cast that variable to ensure I can access the methods.

Take this example, so that you know what I'm talking about:

public class BaseClass
{
  protected var the_holder_var:Object;

  public function BaseClass()
  {
    //Whatever abstract implementation here...
  }
}

Now, my subclasses of that base class usually use an interface but for simplicity sake, I'll just write it without it.

public class AnExtendedClass extends BaseClass
{
  public function AnExtendedClass()
  {
    //Instantiate my own class into the base class variable
    this.the_holder_var = new ACustomClassOfMine(); 

    //Then I can use the 'hackish' getter function below to 
    //access the var's functions.
    this.holder_var.somefunction()
  }

  private function get holder_var():ACustomClassOfMine
  {
    return this.the_holder_var as ACustomClassOfMine;
  }
}

This works and I'm sure it will make some ppl cringe (I sometimes cringe at it too). So now, my question, is there a way to recast/retype that base var in my extended subclass?

kinda like this:

public class ExtendedClass extends BaseClass
{
  //Not possible I know, but as a reference to see what I'm asking about
  //Just want to change the type....
  override protected var the_holder_var:ACustomClassOfMine;

  public function ExtendedClass()
  {
    //Then I can forget about having that hackish getter method.
    this.the_holder_var = new ACustomClassOfMine();
    this.the_holder_var.somefunction();
  }
}

I was thinking of typing most of my base class vars that I use as holders as type * and retyping them as I extend the class. (I could use it here too but yeah...) Thoughts? Comments? Ideas?

Upvotes: 1

Views: 1208

Answers (3)

epologee
epologee

Reputation: 11319

I actually think your code (apart from the hypothetical addition at the end) is pretty alright. The practise of adding accessors to solve the type issue you're dealing with is a solid one. I would advise to rename the accessor to show it is a cast, maybe get holderVarAsCustom():ACustomClassOfMine (I'm also not a big fan of the underscores, that's another language's convention), but that's personal preference. What I'd do to solve your last problem is just create a matching setter function:

private function set holderVarAsCustom(value:ACustomClassOfMine):void {
  this.the_holder_var = value;
}

This way you can access the correctly typed holder var for both read and write operations with complete type safety:

holderVarAsCustom = new ACustomClassOfMine();
holderVarAsCustom.someFunction();

I would definately advise against dropping the type safety by including arrays and what not, that just makes it unstable.

Upvotes: 1

Manuel Leuenberger
Manuel Leuenberger

Reputation: 2367

I would not try to tinker this behaviour, since you can't change the declared type of a variable once declared, no matter how hard you try. What I do in such cases, I either cast the variable if I use it sparingly or the object it references may change, or I add another variable with the type I want and let the other variable point to the new one. Like this:

public class A {

    protected var object:Object;

    public function A() {
        //Whatever abstract implementation here...
    }

}

and

public class B extends A {

    protected var other:MyClass;

    public function B() {
        super();
        this.other = new MyClass();
        this.object = this.other;
    }

}

Having it this way, class A uses the object via the this.object reference, and class B can use the this.other or both. But both references point to the same object. The only issues with this are:

  • having two references for in the same class to the same object is ugly (so are untyped variables and casts)
  • if the object one of them may point can change during runtime, you must be really carefull to synchronize these changes

Upvotes: 0

JimmyDeemo
JimmyDeemo

Reputation: 333

I must admit that i'm a little confused as to why you want to do this, but here goes. Could you not utilise the fact that Array's can hold different data types. So something like this:

public class BaseClass
{
      protected var customStorage:Array;

      public function BaseClass()
      {
        //Whatever abstract implementation here...
      }
}

You could then access it with an associative method and a property:

public class AnExtendedClass extends BaseClass
{
   private static const myName:String = "myName";

   public function AnExtendedClass()
   {
     //Instantiate my own class into the base class variable
     customStorage[myName] = new ACustomClassOfMine(); 
     objectIWant.somefunction()
   }

   private function get objectIWant():ACustomClassOfMine
   {
     return ACustomClassOfMine(customStorage[myName]);
   }
}

Is that any better?

Upvotes: 0

Related Questions