Is there a way to override the width (for a getter) on a Sprite?
I see examples of how to override the setter but not the getter
I need to do something like
override public function get width():Number {
if (onecase) {
return this width;
} else {
return another width;
}
}
Yes you can.
override public function get width():Number {
if (onecase) {
return myWidth;
} else {
return super.width;
}
}
super.width is will be basic Sprite getter.
the setter/getter method signatures need to be identical since ActionScript 3.0 doesn't support function overloading. the x, y, width and height properties of display objects are Number objects, not int as one might assume.
//Class Properties
private var widthProperty:Number;
~
//Set Width
override public function set width(value:Number):void
{
widthProperty = value;
}
//Get Width
override public function get width():Number
{
return widthProperty;
}
Related
The purpose of inheritance is to inherit and extend.
So my question is that if child class have more method that will it break the LSP ?
So in my example I have 2 classes Rectangle and Square. Square is child of Rectangle. Now both have 2 different methods HelloRectangle and HelloSquare. So will it breack LSP or not ?
public class Rectangle
{
//public int Width { get; set; }
//public int Height { get; set; }
public virtual int Width { get; set; }
public virtual int Height { get; set; }
public Rectangle()
{
}
public Rectangle(int width, int height)
{
Width = width;
Height = height;
}
public override string ToString()
{
return $"{nameof(Width)}: {Width}, {nameof(Height)}: {Height}";
}
public string HelloRectangle()
{
return "Hello Rectangle";
}
}
public class Square : Rectangle
{
public override int Width // nasty side effects
{
set { base.Width = base.Height = value; }
}
public override int Height
{
set { base.Width = base.Height = value; }
}
public string HelloSquare()
{
return "Hello Square";
}
}
child class have more method that will it break the LSP ? :- Not it will not break LSP unless you change the behavior of common method. When you substitute child class then you can only access method which drive from base regardless of more/other methods in child class for example
Public class A
{
public int sum ()
{
}
}
public class B
{
public int sum ()
{
// same behaviour as per method in A
}
public int divide()
{
}
}
// So calling of method
B b = new B();
b.Sum();
//So If you substitute with drive class then
B b = new A();
// Here in the below line there is no impact of other methods of child class Thus child class have more method will not break the LSP
b.Sum();
Hence both have 2 different methods HelloRectangle and HelloSquare. So it will not break LSP.
But on other hand setwidth and setheight break LSP because in case of square, behavior of setwidth and setheight has been changed
I hope you got the answer and not confused with setwidth and setheight method in your case.
The substitutability defined by the LSP applies in only one direction: a child may replace its parent. It is never the case that a parent is expected to replace its child, irrespective of the LSP.
In statically-typed languages, substitution is only possible in one direction. For example, in Java we can show that substitution only compiles when Child replaces Parent.
class Parent {
void method() {
System.out.println("Hello Parent");
}
}
class Child extends Parent {
void anotherMethod() {
System.out.println("Hello Child");
}
}
class Main {
public static void main(String... args) {
Parent parent = new Parent();
Child child = new Child();
useParent(child); // compiles: Child is syntactically substitutable for Parent
useChild(parent); // error: Parent is not syntactically substitutable for Child.
}
static void useParent(Parent parent) {
parent.method();
}
static void useChild(Child child) {
child.anotherMethod();
}
}
It's not a problem that Child has anotherMethod(), because Child cannot be replaced by Parent.
I know that this is not allowed before super but I need to do it. I was wondering if there was a legal way to do this in es6?
My code:
class DOMElement {
constructor(aNodeName) {
this.name = aNodeName;
this.create();
}
create() {
let domref = document.createElement(this.name);
document.body.appendChild(domref);
return domref;
}
}
class Button extends DOMElement {
constructor(aLabel) {
this.label = aLabel;
super('button');
}
create() {
let domref = super.create();
domref.textContent = this.label;
}
}
If I don't set this.label before calling super('button') in Button.prototype.create then domref.textContent is set to undefined.
There's no 'legal' way.
It can be be a getter in cases where static property value is supposed to be used by parent class on construction:
get label() {
return 'label';
}
In this case this means that class design is just wrong. There's nothing in parent class that would impose such restriction. Actually, label is only used by child class. It should be:
constructor(aLabel) {
super('button');
this._domref.textContent = alabel;
}
create() {
// if parent class is user-defined, it should be done there
// instead of returning a value, because it doesn't make sense
// to leave an important part of the object without a reference
this._domref = super.create();
}
I try to implement footer datagrid with allowMultipleSelection properties.
But in my case, it seems not to work.
Can you help me to implement this function.
Thanks
package fr.component.dgFooter
{
import mx.controls.DataGrid;
import mx.controls.dataGridClasses.DataGridColumn;
public class FooterDataGrid extends DataGrid
{
protected var _footerAllowMultipleSelection:Boolean=false;
public function FooterDataGrid()
{
super();
if(_footerAllowMultipleSelection){
this.allowMultipleSelection=true;
}
else{
}
}
public function get footerAllowMultipleSelection():Boolean
{
return _footerAllowMultipleSelection;
}
public function set footerAllowMultipleSelection(value:Boolean):void
{
_footerAllowMultipleSelection = value;
}
protected var footer:DataGridFooter;
protected var footerHeight:int = 22;
override protected function createChildren():void
{
super.createChildren();
if (!footer)
{
footer = new DataGridFooter();
footer.styleName = this;
addChild(footer);
}
}
override protected function adjustListContent(unscaledWidth:Number = -1,
unscaledHeight:Number = -1):void
{
super.adjustListContent(unscaledWidth, unscaledHeight);
listContent.setActualSize(listContent.width, listContent.height - footerHeight);
//this deals w/ having locked columns - it's handled differently in
//the dg and the adg
footer.setActualSize(listContent.width+listContent.x, footerHeight);
footer.move(1, listContent.y + listContent.height + 1);
}
override public function invalidateDisplayList():void
{
super.invalidateDisplayList();
if (footer)
footer.invalidateDisplayList();
}
}
}
Your code only checks _footerAllowMultipleSelection and sets allowMultipleSelection in the constructor, when the value is always false.
Set the allowMultipleSelection property in the setter of footerAllowMultipleSelection. You can also change the initial value of _footerAllowMultipleSelection to true.
But why are you wrapping it in a getter and setter at all? The allowMultipleSelection property is already public, so it can be set without providing another property in your subclass that does the exact same thing.
I have a base class like this
class Base {
public var space:Number;
}
which gets extended by
class Desc extends Base {
override public function set space( space:Number ):void {
//code
}
}
This doesn't compile. Say, you don't have control of the base class, what ways is there implement the same thing?
The obvious is create a function setSpace(), but this object is being embedded in an already existing system that use the public space.
Thanks in advance.
Your base class should be defined that way:
class Base {
// Don't use public variables. Make them private and define setters and getters
private var space_:Number;
public function get space():Number {
return space_;
}
public function set space(v:Number):void {
if (space_ === v) return;
space_ = v;
}
}
And then it can be overriden that way:
class Desc extends Base {
override public function set space( space:Number ):void {
//code
}
}
Edit:
I missed the part where you say you don't have control over the base class. In that case, hope that space is defined as a getter/setter (it should be if the class is implemented properly). If not, you'll indeed have to use a function such as getSpace and setSpace.
From Adobe:
Class member variables that are declared using the var keyword cannot
be overridden in a subclass.
Using a setter is not an option in your case. If you need to preserve the interface, use composition instead of inheritance:
class Desc {
private var _base:Base;
public function set space(space:Number):void {
//code
this._base.space = space;
}
}
I have a class which extends the Sprite object in as3. I need to be able to override the transform.matrix setter in this class but haven't been successful in doing so.
I've tried many things, along with creating my own separate class which extends the Transform class and then overrides its set matrix function, and set my transform = new CustomTransform(). Sadly this didn't work.
In code this is what i tried:
public class MyClass extends Sprite
{
public function MyClass()
{
super(); transform = new MyTransform(this);
}
}
class MyTransform extends Transform
{
public function MyTransform(dp:DisplayObject)
{
super();
}
override public function set matrix(value:Matrix)
{
super.matrix = value;
customcode();
}
}
All help is greatly appreciated!
This seems to work:
public class MyClass extends Sprite
{
public function MyClass()
{
super();
transform = new MyTransform(this,super.transform);
// i'm drawing a rect just to see the results of scaling
graphics.beginFill(0xff0000);
graphics.drawRect(0,0,100,100);
graphics.endFill();
}
override public function get transform():Transform {
var tmp:Transform;
if(super.transform is MyTransform) {
tmp = super.transform;
} else {
tmp = new MyTransform(this,super.transform);
}
return tmp;
}
override public function set transform(value:Transform):void {
var tmp:Transform;
if(value is MyTransform) {
tmp = value;
} else {
tmp = new MyTransform(this,value);
}
super.transform = tmp;
}
}
public class MyTransform extends Transform
{
public function MyTransform(dp:DisplayObject,transf:Transform = null)
{
super(dp);
if(transf) {
for(var prop:String in transf) {
this[prop] = transf[prop];
}
}
}
override public function set matrix(value:Matrix):void
{
super.matrix = value;
// customcode();
}
}
Use:
var sp:MyClass = new MyClass();
var mat:Matrix = sp.transform.matrix;
mat.scale(3,3);
trace(sp.transform);
sp.transform.matrix = mat;
addChild(sp);
The problem is that, even if you create and assign your tranform to be of type MyTransform, the getter returns a regular Transform object. There's something weird about how transform objects work in Flash (this is also true for SoundTransform, for instance). There's some kind of cache mechanism implemented in a rather lame way that forces you to reassign the instance if you want to commit your changes.
I mean this pattern:
var t:Transform = mc.transform;
// do something with t
mc.transform = t;
So I think this is related to why your code doesn't work as expected.
To get around this, I'm checking both in the setter and the getter if the trasnform object passed is of type MyTransform. If it is, I use it as is. If it's not, I create a MyTransform object and copy all of the properties from the original Transform. It'd be nice if the Transform class had a clone method, but it doesn't, so I implemented this simple copy mechanism. Not sure if this doesn't mess up with some internal state in Transform (could be the case). I haven't tested it apart from applying a scale, once. You might want to do it, as there could be other side effects I'm not considering. Also, this is probably not the most performant. But I can't think of another way to have your matrix setter called.
Edit
Using a static/global dispatcher is not a good idea except you really need it to be global. Implementing IEventDispatcher, since you can't directly extend EventDispatcher, is what you want.
The code needed for that is a bit verbose, but it's a no-brainer anyway. All you need is having an internal instance of event dispatcher and implement the methods of the interface. In said methods, you forward the parameteres to the actual dispatcher.
public class MyTransform extends Transform implements IEventDispatcher
{
private var _dispatcher:EventDispatcher;
public function MyTransform(dp:DisplayObject,transf:Transform = null)
{
super(dp);
_dispatcher = new EventDispatcher(this);
if(transf) {
for(var prop:String in transf) {
this[prop] = transf[prop];
}
}
}
override public function set matrix(value:Matrix):void
{
super.matrix = value;
// customcode();
}
public function dispatchEvent(event:Event):Boolean {
return _dispatcher.dispatchEvent(event);
}
public function addEventListener(type:String,listener:Function,useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {
_dispatcher.addEventListener(type,listener,useCapture,priority,useWeakReference);
}
public function removeEventListener(type:String,listener:Function,useCapture:Boolean = false):void {
_dispatcher.removeEventListener(type,listener,useCapture);
}
public function hasEventListener(type:String):Boolean {
return _dispatcher.hasEventListener(type);
}
public function willTrigger(type:String):Boolean {
return _dispatcher.willTrigger(type);
}
}