BillPull
BillPull

Reputation: 7013

Combining two identical sub classes

So I have two sub classes that extend different base classes in Flex how can I combine these so that I am not repeating myself.

Basically I have something like

public class A extends B {
 // methods
}

public class C extends D {
 // same methods as class A
}

any way to combine this so that I am not repeating the same code twice.

Upvotes: 0

Views: 55

Answers (3)

Nazar Merza
Nazar Merza

Reputation: 3454

You have two child classes (extending different parents) that implement the exact same methods.

public class B {}
public class D {}
public class A extends B {
 // methods
 m1();
 m2();
 ...
}

public class C extends D {
 // same methods as class A
 m1();
 m2();
 ...
}

Now lets make some points about it.

  • In assigning a method to a class, the basic idea is that, that method or behaviour really belongs to that class - it is really a property of that class or type. For example, breathing for Animal. When this is the case, the behaviour is tied to class state (or data, or attributes, or variables). If a method does not access the class variables in any ways, then, that method may not belong there. At least it is the general rule.

Now, in your case, you have m1(), m2(), ... methods that appear in two different classes. This raises the possibility that they may not be really tied to the state of those classes. If so, then the better solution is to completely remove them into a new class.

If you do so,

  1. You will also get rid of two classes, A and C, which now exist only for this purpose.
  2. You get rid of two inheritance relationships. This makes you code much simpler.
  3. And, you will achieve your objective of not repeating your self.

--

//Parent classes (child classes are now gone)
public class B  {} 
public class D  {} 

--

// Your new class
public class X {
 // methods that previously were in A and C
 m1();
 m2();
 ...
}

Upvotes: 1

Amy Blankenship
Amy Blankenship

Reputation: 6961

Favor composition over inheritance

So, the question is, how should you compose the solution?

One possibility is to use Decorator pattern. This is essentially a wrapper around your existing Classes. To make this work, your Classes will probably need to implement an Interface that exposes whatever you'll need to do the job.

So something like:

public interface IFoo {
   function get name():String;
   function set name(value:String):void;
}
public class A extends B implements IFoo {
   protected var _name:String;
   public function get name():String {
      return _name;
   }
   public function set name(value:String):void {
      _name = value;
   }

}

public class C extends D implements IFoo {
   protected var _name:String;
   public function get name():String {
      return _name;
   }
   public function set name(value:String):void {
      if (_value != _name) {
         _name = value;
         dispatchEvent(new Event('nameChanged'));
      }
   }

}

public class FooDecorator {
   protected var _foo:IFoo;
   public function FooDecorator(foo:IFoo) {
      _foo = foo;
   }
   public function sayName():void {
      trace('foo name is', _foo.name);
   }
}

Another solution is to give both A and C member variables of a fifth type that encapsulate the behavior (like what Jeffry said, but I prefer to obey the law of Demeter where possible):

class NameSayer {
   function sayName(name:String):void {
     trace('foo name is', _foo.name);
   }
}

then

public class A extends B {
   public var name:String;
   public var sayer:NameSayer;
   //note that this method would be identical in both Classes
   //but this is OK because the underlying logic is encapsulated
   //and can be easily changed
   public function sayName():void {
     if (sayer) {
        sayer.sayName();
     }
   }
}

I think many developers get too hung up on zealously following DRY and, as Jeffry says, this can cause other, worse, problems in your architecture. Which, if any, of these solutions is appropriate will depend on exactly what you're trying to accomplish.

Upvotes: 1

JeffryHouser
JeffryHouser

Reputation: 39408

Although, I have mixed feelings about its use; you can use the include directive.

Create a file, like this, named sharedMethods.as (or whatever you want). This is not a real class; it just includes code snippets:

public var mySharedMethod(mySharedMethodArguments:ArgumentType):void{
  // do something
}

Then you can include it in your your other classes:

public class A extends B {
 include "sharedMethods.as";
}

public class C extends D {
 include "sharedMethods.as";
}

The code from your include file will be compiled as part of Class A and Class C.

You could also put your shared code in another class and have an instance of that class in both A and C. Then you either have to write wrapper methods or drill down the calls sort of like this:aInstance.sharedCodeObject.sharedMethod();

My intuition is that if you run into this a lot; you may have a problem with the object model that needs some refactoring.

Upvotes: 0

Related Questions