When 'SubClass' extends 'SuperClass', when it inherit its methods and properties, it creates methods and properties that distinguishes from the 'SuperClass'?
Or if I create an instance of 'SubClass' and I try to modify a property, that was inherited from 'SuperClass', am I modificating the super class property also?
Thanks.
EDIT
package {
public class SubClass extends SuperClass {
public function SubClass() {
trace('superclass value n='+superClass.n+'\n');
trace('subclass changes inherited n'+'\n');
n = 3;
trace('subclass value n='+n+'\n');
trace('superclass value n='+superClass.n+'\n');
}
}
}
Returns me:
superclass value n=-1;
subclass changes inherited n;
subclass value n=3;
superclass value n=3;
I will explain it in short.
We have two classes - Subclass and SuperClass.
SuperClass have four methods:
private function methodPrivate():void;
protected function methodProtected():void;
public function methodPublic():void;
internal function methodInternal():void;
From the Subclass you:
Cannot access methodPrivate():void;
Can access methodProtected():void; but just like your private method, it means, you cannot access it from outside of Subclass.
Can access methodPublic():void; and everything can access if from outside of Subclass also.
methodInternal():void; is available for classes from the package of SuperClass.
You can however override these methods. Overriding doesn't change a methods of SuperClass but change them only in SubClass.
override public function methodPublic() : void {
// your additional code
super.methodPublic(); // eventually calling the same method of SuperClass, you can pass arguments to it also
}
As you know, your SuperClass can also have variables, that also can be public, protected, private or internal. You cannot override them, but you can do this with getters or setters however.
You can access variables that are created as public or protected by using a word "super" like this: super.someVariable .
So everything is up to you, if you want to create a different variables of the same name in SuperClass and SubClass, just declare one as private in SuperClass. If you want to have one variable that SuperClass and SubClass both can access - just declare it as protected or public.
Hope that was clear.
When you create a blank SubClass the extends SuperClass, you are creating a new class that provides the same interface (with the same implementation) to the parent class.
That is to say, if your parent class contains a method doSomething, your SubClass, without ever actually writing it, will have the doSomething method available as well. The one caveat to this is if the method is marked private, in which case the inheriting class, SubClass, will not have access.
package {
public class SuperClass {
public function SuperClass():void {
self.doSomething();
}
public function doSomething():void {
trace("doing something");
}
}
package {
import SuperClass;
public class SubClass extends SuperClass {
public function SubClass():void {}
}
}
Once you have this relationship established, you can decide whether calling doSomething on an instance of SubClass will behave differently than the default implementation, defined in SuperClass. If you want the same behavior, you leave it as is. If you want different behavior, then you override the parent class' method, using the keyword override.
package {
import SuperClass;
public class SubClass extends SuperClass {
public function SubClass():void {}
override public function doSomething():void {
trace("doing another thing instead");
}
}
}
Now something that calls doSomething on an instance of SubClass will get modified behavior. But the default implementation has not been touched. Instanced of SuperClass are not modified by this overriding of a method. Only instances of SubClass will be affected.
This is the same case for properties.
There is one exception to this, and that is static properties. A static property is a property of the class, not of an instance of the class. Static properties are not inherited. A static property looks like this:
package {
public class SuperClass {
public static var i:int = 0;
public function SuperClass():void {
}
public function doSomething():void {
trace("doing something");
}
}
The SubClass class will not have a reference to a static property i. However, a SubClass instance can change the static value of the SuperClass. As an example:
package {
import SuperClass;
public class SubClass extends SuperClass {
public function SubClass():void {}
override public function doSomething():void {
trace("changing something in SuperClass");
SuperClass.i = 1;
}
}
}
Now, the SuperClass's static variable i has a value of 1, instead of 0. In this way a SubClass has the potential (although it is the same potential any code has with the right access privileges) to change the properties of SuperClass.
I hope this helps.
Related
for a parent class A contains a protected method f() :
public class A {
protected function f():void
{
}
}
public class B extends A{
}
when i create an mxml and create an instance of B with imports all of A and B (are in the same package)
B b = new B();
//the problem :
b.f(); // inaccessible method !!
This is expected. You need to read more about OOP.
What you are missing here is that trying to call f() on an instance of A would have the same effect. By definition only public methods are callable. Protected methods are only available for call and override inside the implementation of subclasses and super classes, they are not public and so they are not callable on instances outside the scope of subclasses. Protected are very much like private methods except that they are available for call and override within the scope of subclasses.
I'm developing a game in AS3. There is a Weapon superclass, which contains methods such as shoot and reload, which will behave the same across all weapons.
The specific weapons, such as Pistol, Shotgun inherit from this class so they can use these methods. They have public static variables, such as what type of bullet to shoot, rate of fire, bullet spread, that make them unique, and are used in these methods. They need to be public static variables so I can look them up from somewhere else in the core when all I've got there is the type of weapon that was fired.
Is this how I should be trying to do it? How does the Weapon superclass access these variables?
public static const RATE:uint = 2;
That is accessed by the Weapon class either as Weapon.RATE or as RATE. Scope works a little weird when it comes to static objects. I personally don't think you should be able to access the static objects with just RATE, but it works.
Subclasses do not inherit static properties and methods. They belong solely to the class they are created in (which makes sense if you know what a static object really is). So for all classes, even classes that extend Weapon, you must access a public static object via Weapon.RATE.
There is an oddity I have noticed however. If you use the protected access modifier instead of public, classes can access static objects in their super classes via RATE, as if it were created within the class itself. I don't know the logic behind that, but it works.
So:
public class Weapon {
protected var RATE:uint = 2;
public var RATE2:uint = 5;
}
public class Gun extends Weapon {
trace( RATE ); // output 2
trace( Weapon.RATE ); // output 2
trace( RATE2 ); // output Error, access of undefined property
trace( Weapon.RATE2 ); // output 5
}
EDIT: In response to the first comment:
The way superclasses work, an object that extends a class has access to all public and protected objects in the super class.
So let's say the weapon class is this:
public class Weapon {
public function shoot():void{}
protected function reload():void{}
private function aim():void{}
}
You would access those methods within the subclass like you would in the super class itself:
public class Pistol extends Weapon{
public function Pistol() {
this.shoot(); // works
this.reload(); // works
this.aim(); // doesn't work because it is private
}
}
Now if you are looking to abstract things further, you can set up properties within your super class with a protected or public modifier with a default value for all weapons. In your superclass methods, you simply call these values. In the subclass, you change them to be whatever you need them to be
public class Weapon {
public var rate:uint = 2;
public function shoot():void{
// use this.rate here
}
protected function reload():void{}
private function aim():void{}
}
public class Pistol extends Weapon{
public function Pistol() {
this.rate = 5; // value of rate is now 5 and will be used in shoot()
this.shoot(); // works
this.reload(); // works
this.aim(); // doesn't work because it is private
}
}
I have a rather simple theoretical question regarding OOP (in AS3) that I don't know how to google:
I need something like an abstract class, which would require that dependant class implements some interface, like this:
Interface ISomething
{
public function somethingize(otherThing:type):void;
}
abstract public class AbstractSomething implements ISomething
{
public function AbstractSomething()
{
// ...
}
public function doSomething():void
{
//code here
// ...
this.somethingize();
// ...
}
}
Is the only way to achieve such a thing is to drop an "abstract" keyword, and move somethingize to SomethingWrapper (with an implementation of throwing an "unimplemented exception"), or is there some better way to model it?
ActionScript doesnt support Abstract classes (unfortunately).
I think there are a few techniques out there to try and mimic abstracts, but my way is too just throw errors in my abstract classes to stop them being used directly, eg:
public class AbstractSomething implements ISomething
{
public function AbstractSomething()
{
throw new Error("this is an abstract class. override constructor in subclass");
}
public function doSomething():void
{
throw new Error("this is an abstract class. override doSomething in subclass");
}
}
Without more information about the specific implementation, I would prefer composition over inheritance in this case, specifically dependency injection.
public interface ISomething {
function somethingize(thing:*):void;
}
public class SomeWorker {
private var _something:ISomething;
public function SomeWorker(something:ISomething) {
this._something = something;
}
public function doSomething():void {
// work
this._something.somethingize(obj);
// more work
}
}
Inherrited classes of SomeWorker could inject the correct implementation of ISomething for the work they need to do, or that dependency could be resolved somewhere else.
I want to subclass "superClass" and override one of it's functions.
public class superClass {
protected function f1(...) : Boolean {...}
protected function f2(...) : Boolean {...}
...
protected function f100(...) : Boolean {...}
}
public class subClass extends superClass {
// override f1 in the subclass
protected override function f1(...) : Boolean {...}
}
The problem is that the "superClass" is loaded from a swf. I do not have a reference to the class definition in my project. Is there a way to do something like below?
public class subClass {
private var superClassObject: Object;
// construct from an instance of superClass
public function subClass (s : Object) {
superClassObject = s;
}
private function myF1(...) : Boolean {...}
override InvokeFunction (fname: string, args: Array) : Object {
if (fname == "f1") {
return myF1(args);
} else {
return superClassObject.InvokeFunction(fname, args);
}
}
}
I'm not sure how function call is implemented in AS. What should "InvokeFunction" be?
You should use .swc , not .swf. The class you want to extend must be available at compile time, not at runtime. Anyway if using of swf is mandatory for you, you could use different techniques to 'override' functionality.
Besides inheritance there are other OOP concepts (Composition, Aggregation,etc...) and design patterns(Proxy,Adapter,etc...) for changing functionality of class. You could use them.
All,
I ran into this funny thing in a different post. It was pointed out to me that you can explicitly override a constructor... which doesn't seem necessary, and I am a little surprised it even compiles. Take a look:
public class TestClass
{
public function TestClass() {}
}
public class TestClass2 extends TestClass
{
public override function TestClass2() {}
}
Explicitly calling override on the constructor might just be a no-op, as it is certainly not necessary. My question: Is there a subtlety here that I am missing? Does explicitly overriding the constructor tell the compiler something?
public class TestClass
{
public function TestClass() {}
}
public class TestClass2 extends TestClass
{
public override function TestClass2() {
super();//this makes call to the default constructor
}
i think it's just a bit of freedom provided by as3 syntax :)imho bytecode of an swf with overriden contstructor is equal to one of swf with a normal one