Can someone tell me if this class structure is bad?
class abstract Parent{
public Child Foo(){
return new Child();
}
}
class Child : Parent{}
I've heard that referring to a derived type from a base type is always bad and signs of bad design. Can someone tell me why this is bad or even if it is bad?
It looks to me like you are using the base class as a factory. I would recommend against this design because it reduces the cohesion of the base class (it's both base class and factory) and increases coupling in the base class (as it references the derived class(es)).
Create a factory class separate from the base class and these issues go away.
To elaborate on dkackman's answer, your factory ideally would return objects of child types, but declared as the parent type.
class Factory
{
public Parent Foo()
{
return new Child();
}
public Parent Bar()
{
return new OtherChild();
}
}
The basic idea is that your calling code shouldn't care which child class it gets back. This is one concept of the Liskov Substitution Principle.
It certainly smells bad, in many levels. Just ask yourself what would happen if someone extends Child ; or it another subclass of Parent (instead of Child) is made.
It's hard to imagine a case that would justify this design (perhaps it exists, you could explain what you are trying to achieve). (Are you familiar with the factory pattern?)
In any case, to get a reasonable behaviour for such design I guess one should accept and embrace the coupling, even try to enforce it, by making the Child class final/sealed (impossible to extend) and thinking both classes as a whole. But then again, that could (almost surely) better be achieved with another cleaner design.
I can't say anything wrong on your design. To say more concretely I must know your purpose of doing so. But whatever your purpose is, you will miss polymorphism. So, think from the client code perspective, you are exposing super class details just to get the sub-class instance. Why on earth we do that? Atleast, I don't. Remember the design principle, we always want a highly cohesive class. Here you are breaking that principle by providing factory method to create a sub-class instance.
rajan
Related
everyone! I wonder is it bad practice.
In this case I pass the container to TicTacToe class,TicTacToe pass the container to MainMenu class,MainMenu class pass the container to Engine and etc. Engine pass to GameOver class and GameOver pass to TicTacToe the same sprite on play again.And that all display objects are added to this Sprite container.
Main(){
var container:Sprite = new Sprite();
var game:TicTacToe(container);
addChild(game);
}
TicTacToe(containerPar:Sprite){
this.container = containerPar;
MainMenu(this.container);
}
Is this a good practice?
The other way that I think is like tell of almost all my classes like Engine and MainMenu to extend sprite and I think is not a good idea.
Is there any other practices to add display objects to DisplayObjectContainer wich is added to stage ?
I want to know because i think it is very important and there is not much information on the internet.Thanks to everyone!
The syntax seems a bit messed up, it doesn't show too well what you are trying to achieve.
There are many ways you can reference a Sprite, or anything else, from everywhere.
You can use a singleton class, or a static variable for example.
Lets say you have a general Game class. In the class itself you can have a static variable named "container" that references the sprite you want. You can retrieve it with a getter or with a static method. So that you could, anywhere:
import Game;
var container:Sprite = Game.container;
// or
var container:Sprite = Game.getContainer();
this makes overall better OOP and cleaner code.
I hope this helps.
In other words are these two different blocks of code fully equivalent?
ES6 class extend based
class Child extends Parent {
// Define my subclass
}
var myInstance = new Child();
Object.assign based
var myInstance = Object.assign(new Parent(), {
// Define my subclass
}
In my particular use case I am trying to extend (Facebook's) Flux Dispatcher. In their examples they use Object.assign. I would like to ES6 class extend, but I am worried that there are subtle differences between the two so I should stick with Object.assign.
No, these code blocks are not equivalent
In the class inheritance example you will get a new constructor which makes objects having features from parent class.
Extending objects via Object.assign is a example of mixins.
You just add some properties to one instance but not change all future children.
Unlike child classes, an instance after extension will still have the constructor property pointing to the Parent. It means that you can't recognize extended child among non-extended, because they all have the same constructor and operator instanceof will give the same result. Also you can't get access to overridden methods in child, because you will lose the link to it.
As for flux's dispatcher in this example, you can't extend it via class inheritance, because there is no constructor which you can provide as a parent.
So if a getter is finally a function, why not use just a function? I guess to enforce using that function to set/get a value any time needed, any other reason?
A getter is a function (as far as POO languages I know).
The idea is to delegate the ability to modify or to get an attribute to only one function by class, in case of there were special checks to perform before applying the getter or setter.
Properties are used just to improve readability or ease the API, without breaking encapsulation. For example, if you have a Rectangle class and you want to increase by 10 the width of an instance, without properties, you would do something like:
rect.setWidth(rect.getWidth() + 10)
While, using properties, you could just write:
rect.width += 10
Which is clearer. And because properties are functions, you can do all the checks that you need. Moreover, it doesn't even matter if the width is actually stored in the class; maybe the rectangle is stored as a pair of points (i.e. upper-left and lower-right), but the property would handle it. Additionally, you could write properties that access the same data in different ways: for example, you could have width, height, top, bottom, left and right properties, and all of them would affect the same internal data of the class, but would make it easier to use and more readable.
As in this adobe documentation, there is only three types of caps for drawing lines:
square, round, none.
Isn't there a custom shape for caps style? anyone knows? : )
There's only 3 types of CapsStyle available in actionscript-3.
However if you want another types of CapsStyle you have to extend a class where you want to implement.
For example if you want to implement on graphics.lineTo() function then you have to extend graphics class to your own yourgraphics class and override the lineTo method and add another capsstyle type.
Pretty much complex I guess.
I am trying to create a way of controlling movieclip depths, which movieclip is show above another, so that I can set the depth of a movieclip to any number and they will be displayed with higher values above lower values.
I was thinking of creating a MovieClipDepth class that extends MovieClip with the added property depth, and a Container class that extends DisplayObjectContainer which all objects will be placed inside of.
The Container class will override the addChild method to update the child display order when a child is added.
What I need help with is how do I reorder the children according to
their depth value?
As you can read in the comment below your question, there are several methods for this.
But actually, what you asked "set the depth of a movieclip to any number" can't really be done in AS3. If i'm correct, you could do this in AS2, so...
... how was it ...
_root.createEmptyMovieClip("mc", -1000);
or
_root.createEmptyMovieClip("mc1", 1);
_root.createEmptyMovieClip("mc2", 10);
worked, but does not work in AS3. In AS3 depth starts with 0 and you can't force a DisplayObject to sit on a level what is not continous from zero.
So the depths' of 3 movieclips in a container is only possible with these values: 0, 1, 2.
Depth can't be a negative number for example.
Now, if you want to build a custom depth manager, you can do that, but you have to consider these facts.
So to say, you could create virtual depths.
So I guess, you could override the addChildAt method for example. At the moment, if you would give a wrong number: negative, or higher then the number of children, flash would give back the error:
RangeError: Error #2006: The supplied index is out of bounds.
So mc.addChildAt(newchild, -1000) gives an arror.
But with overriding the method, you could make a trick, so you could store the depths in an array. You could store any numbers and then transform that order for the needs of AS3.
Like pairing the depths with the added children, sorting the array by the depths, then manage the children according to the order.
If you have more questions, feel free to ask, hope this gets you closer to the solution.
I suggest you take a look at this tutorial :
A Tour of Depths Management Methods on the website http://www.flashandmath.com/. I presume you not a newbie .
The link is this:
http://www.flashandmath.com/intermediate/depths/index.html