I have seen examples online about the Single Responsible principle.
They always use IoC/DI as an example.
They move the code from class A to class B and pass class B as reference.
See code below:
class B {}
class A {
b;
// reference used
constructor(b) {
this.b = b;
}
doStuff() {
...
this.b.doSomeOtherStuff();
}
}
But the Single Responsible principle is about to increase the coherence.
Theoretically the code above would also follow the Single Reponsible principle without
passing down a reference to class B, right?
Like this:
class B {}
class A {
// no reference
constructor() {
this.b = new B;
}
doStuff() {
...
this.b.doSomeOtherStuff();
}
}
In the book Clean Code by Robert C. Martin there is an example reagarding the SRP where he uses only composition.
So I would say yes, Singe Responsible Priciple is valid without IoC/DI.
In the example below hes directly creating an instance of the LinkedList.
public class Stack {
private int topOfStack = 0;
// creating a direct instance here
List < Integer > elements = new LinkedList < Integer > ();
public int size() {
return topOfStack;
}
public void push(int element) {
topOfStack++;
elements.add(element);
}
public int pop() throws PoppedWhenEmpty {
if (topOfStack == 0)
throw new PoppedWhenEmpty();
int element = elements.get(--topOfStack);
elements.remove(topOfStack);
return element;
}
}
I have a Parent type with one of its fields is a Discriminated Union (JsonSubTypes).In my example below i keep the Discriminant (id) inside my child field.
What i want to know is : is it possible to have the discriminant outside my child object and directly in the parent ?
What works
public class Parent{
Child childField{get;set;}
}
[JsonConverter(typeof(JsonSubTypes),CHILDTYPE)]
[JsonSubTypes.KnownSubTypes(typeof(Child1),CTYPE.Child1)]
[JsonSubTypes.KnownSubTypes(typeof(Child2),CTYPE.Child2)]
public abstract class Child{
public enum Discriminator{
Child1=0,
Child2=1
}
private const string CHILDTYPE="childType";
[JsonProperty(CHILDTYPE)]
public abstract Discriminator Kind{get;} //i want this moved to parent
}
public class Child1:Child{
public int Value{get;set;}
public override Kind=>Discriminator.Child1;
}
public class Child2:Child{
public bool Value{get;set;}
public override Kind=>Discriminator.Child2;
}
Usage
List<Parent>parents=new List<Parent>{new Child1{Value=3},new Child2{Value=True}};
var str=JsonConvert.SerializeObject(parents);
List<Parent>parents=JsonConvert.DeserializeObject<List<Parent>(str);
What i want
public class Parent{
private const string CHILDTYPE="childType";
public enum Discriminator{
Child1=0,
Child2=1
}
public abstract Discriminator Kind{get;}
Child childField{get;set;}
}
[JsonConverter(typeof(JsonSubTypes),CHILDTYPE)]
[JsonSubTypes.KnownSubTypes(typeof(Child1),CTYPE.Child1)]
[JsonSubTypes.KnownSubTypes(typeof(Child2),CTYPE.Child2)]
public abstract class Child
{
}
As you can see what i want is to move my Kind field from the Child and into the Parent.Can i somehow accomplish this? I want to keep everything the same , just instead of a Json like this:
{
childField:{ Kind:3}
}
I need to accomodate for a json like this:
{
Kind:3
childField:{}
}
Can i accomplish this ? Can i somehow decorate the parent to know to deserialize one of its fields based on another ?
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 have the two following classes:
public class Parent{
static internal const _name:String = "Parent";
public function get name():String{
return _name;
}
}
public class Child{
static internal const _name:String = "Child";
}
If I create an instance of class Child and call its name() getter, since it will call the name() method it inherits from Parent, it returns "Parent". I could, of course, override the name() method:
public class Child{
static internal const _name:String = "Child";
override public function get name():String{
return _name;
}
}
That returns "Child". However, it seems silly to have to copy the exact same code of the method from the parent. Is there any simpler way to do this?
I would take a different approach by making the "name" property a requirement for the parent's constructor:
public class Parent
{
static internal var _name : String;
public function Parent(name : String = "Parent") {
_name = name;
}
public function get name() : String {
return _name;
}
}
Child Class:
public class Child extends Parent
{
public function Child() {
super("Child");
}
}
Firstly, you cannot override static methods or properties - they are not inherited, so no override for them.
Secondly, if you declared a constant to be of a complex type, it is not really a constant. I.e. if it is an object, then you can change its keys / values, if it is an array, you can add / remove members and so on.
But the desire to make this functionality more generic is understandable. So, what I'd do:
Have some property outside both parent and child, let say in class X, or package Y. Let it be package Y. So, you'd create a dictionary in package Y, let it be Y.names and in your name getter you'd do:
import Y.names;
. . .
public function get name() {
return names[(this as Object).constructor];
}
your names variable would be:
package Y {
public var names:Dictionary = generateNames();
internal function generateNames():Dictionary {
var result:Dictionary = new Dictionary();
result[ChildClass] = "child";
result[ParentClass] = "parent";
. . .
return result;
}
}
This way it would be sufficient to only implement name getter in super-class, and all inheriting classes will be able to use super-class code as is, no need to change anything. However, this means that some (maybe important) information pertaining to this class will be stored elsewhere (may be difficult to find, this is not the common way people program in AS3).
your implementation of get name should look like this, then the getter is one and each of the new classes needs to have it's own public static var _name defined:
//in the base class
public function get name():String
{
var _sName:String;
if ((this as Object).constructor._name)
{
_sName = (this as Object).constructor._name;
}
else
{
try
{
var o:Object = getSuperClass(this);
while (o)
{
if (o._name)
{
_sName = o._name;
break;
}
o = getSuperClass(o);
}
}
catch (e:*)
{}
}
return _sName;
}
//as found here: http://www.actionscriptdeveloper.co.uk/getting-the-class-of-an-object-in-as3/
public static function getSuperClass(o: Object): Object
{
var n: String = getQualifiedSuperclassName(o);
if (n == null)
return(null);
return getDefinitionByName(n);
}
the static members can be accessed only via class reference which we can get from constructor object, "this" will point to the current class in the inheritance chain so you can call this in parent class and it will point to a Child in a Child class.
[EDIT]
I've modified it so it tests for existance of the public static property _name if not found on "this" instance then in a loop the parent class is checked until one is found - like inheritance:)
I'm using this feature to create clone method: constructor as helper in clone method implementation
best regards
Why don't you store such a constant within a corresponding function instead of declaring an inaccessible constant?
class Parent {
...
public function get name():String { return 'Parent'; }
}
class Child extends Parent {
...
override public function get name():String { return 'Child'; }
}
By the way, if your Parent class is a descendant of DisplayObject, you should be careful with name property, as it's needed sometimes by operating code, e.g. getChildByName().
I have found something that seems to work. Any feedback is greatly appreciated:
public class Parent{
prototype._name = "Parent";
public function get name():String{
return this["_name"];
}
}
public class Child{
prototype._name = "Child";
}
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;
}