Let's say I have these two subclasses (psuedo code):
Male.class:
include Person.class;
class Male extends Person {
...
}
Female.class:
include Person.class;
class Female extends Person {
...
}
And finally I have this base class:
Person.class:
class Person {
static function makePersonBySettings(settings) {
var person;
if(settings.gender == 'male') {
person = new Male(settings.name);
}
else if(settings.gender == 'female') {
person = new Female(settings.name);
}
return person;
}
}
Parent's static method depends on knowing what Male.class and Female.class are. I can't do importing of subclasses (e.g., import Male.class) at the top of Parent.class because the subclass depends on knowing the parent.
What's the best way to resolve this issue?
You could decouple the factory method (makePersonBySettings) from your parent class by creating a dedicated class to contain factory methods.
class Person {
static function makePersonBySettings(settings) {
var person;
person = new self(settings.name);
return person;
}
}
self will reference your child object.
Male::makePersonBySettings(settings) will return a Male object.
Related
class ExampleClass {
//default constructor
ExampleClass() {
//do stuff
}
//named constructor
ExampleClass.namedConstructor() {
//do stuff
}
}
void main() {
//is there a way to create a variable with datatype to store an object that is constructed only with a specific constructor?
//I have tried something like this, but it returns an error
ExampleClass.namedConstructor variable_1;
}
Is there any way to do this or an alternative? because I need to be able to differentiate between an object that is constructed with the default constructor or with a named constructor.
You can add some identification to classes builded with different constructors and compare entities by unique parameters.
If instances of your classes creating once (Singleton design pattern), you can create entities as constants and compare it by reference:
const administrator = User.administrator();
class User {
final int id;
User(this.id);
factory User.administrator() {
return User(0);
}
factory User.administrator(int id) {
return User(id);
}
}
Is there a way to declare return types of methods or the object-prefix to be the "extendingClass" like you would do in PHP with the static::class?
So for example:
abstract class AbstractModel {
// Should return the database-provider for the given model
dynamic get modelProvider;
// Save instance to Database - Create new if no ID exists,
// else update existing
dynamic save() {
if( id == null ) {
modelProvider.insert(this);
} else {
modelProvider.update(this);
}
return this;
}
}
class ToDo extends AbstractModel {
ToDoProvider get modelProvider {
return ToDoProvider;
}
}
So in this example, obviously AbstractModel does not yet know what the return type of modelProvider will be, but I do know that it will always be the same type for a given child. Also, the return type of the save method would always be the child-class. But when writing it like this I will get an error for overwriting the modelProvider with an invalid return type.
Due to darts javascript-like nature I assume there is no way to actually achieve this like you would in PHP. But then I wonder how to type-save build re-usable code? I am trying to implement a small eloquent like query-scheme for my models so I don't have to write each CRUD method for every model - but I would still like to be precise about the types and not use dynamic everywhere.
So is there a way to do that in dart or am I completely off the track regarding dart standards?
You can use generics:
abstract class AbstractModel<ChildType extends AbstractModel<ChildType>> {
// Should return the database-provider for the given model
ModelProvider<ChildType> get modelProvider;
// Save instance to Database - Create new if no ID exists,
// else update existing
ChildType save() {
if( id == null ) {
modelProvider.insert(this);
} else {
modelProvider.update(this);
}
return this;
}
}
class Model extends AbstractModel<Model> {
}
abstract class ModelProvider<T> {
void insert(T value);
void update(T value);
}
class MyModelProvider extends ModelProvider<Model> {
...
}
Hope one of you angular2 / typescript wizards can help out or at least provide a pointer in the right direction, before I got crazy :-)
Here is what I'd like to
have a parent class that implements it's own defined parent Interface, however using Generic Types so I can when creating a child class provide it with the child's specific and tailored class & data Interface.
the child class should be able to extend the parent data class by
being able to overwrite default/parent set variables
overwriting parent functions() and have the child's version called instead of the parent's default
In the below pseudo code example, I would like the call to the child's (inherited) someOtherfunction() to return "2"...
Am I asking for too much?
I can't seem to find any decent examples on the web...
How do I get this right?
Thank you -
Oliver
(CODE BELOW MAY BE BROKEN, IT'S JUST FOR ILLUSTRATION)
//
// Parent Class
//
export interface ICoreData <T> {
observeItems: Observable <T[]> ;
items: Array <T>;
}
#Injectable()
export class CoreData<T> implements ICoreData<T> {
public observeItems: Observable<T[]>;
private items: Array<T>;
constructor( 'Dependency Injection...' ) {}
coreFunction(): number {
return 1;
}
someOtherfunction(){
return this.coreFunction();
}
}
//
// Child class
//
export interface IMyDataStructure {
name: string;
age: string;
}
export interface ISpecificData extends ICoreData<IMyDataStructure> {
someExtraKey: number;
}
#Injectable()
export class SpecificData extends CoreData<IMyDataStructure> implements ISpecificData {
constructor() {
super();
}
coreFunction(): number{
//
// This function should "overwrite" the parent's original function
// and be called by the parent's someOtherfunction() function
//
return 2;
}
}
You're not asking too much. However you can't use interfaces to accomplish what you're trying to accomplish. You need to extend a class, which can be generic.
An interface is simply a contract, or a blueprint if you like, for a data type. There is no functionality associated with an interface. However in your case you wanted to be able to have methods on the base class; methods you could override in the derived.
The way I usually do this is to declare an abstract base class (so that the base class can't be instantiated itself), and then extend classes from that. Here's an example:
Note, I've removed all the Angular2 cruft in order to keep the example as simple as possible.
abstract class Base<T> {
constructor(public controlled: T) { }
doIt(): string {
return `Base.doIt: ${JSON.stringify(this.controlled)}`;
}
doSomethingElse(): string {
return `Base.doSomethingElse: ${JSON.stringify(this.controlled)}`;
}
};
interface Foo {
foo: string;
bar: string;
};
class Derived extends Base<Foo> {
constructor(foo: Foo) {
super(foo);
}
doSomethingElse(): string {
return `Derived.doSomethingElse: ${JSON.stringify(this.controlled)}`;
}
};
let d: Derived = new Derived({ foo: 'foo', bar: 'bar' });
console.log(`doIt ==> ${d.doIt()}`);
console.log(`doSomethingElse ==> ${d.doSomethingElse()}`);
Output:
doIt ==> Base.doIt: {"foo":"foo","bar":"bar"}
doSomethingElse ==> Derived.doSomethingElse: {"foo":"foo","bar":"bar"}
Playground link.
What i would like to do, is create TreeViewer using databinding for a POJO class, which has multiple list properties, and all of them needs to be observed, and displayed in the viewer.
I would like to display a tree like:
Person
\
|- Dog // dogs list
|- Dog
|- Cat // cats list
|- Cat
|- Cat
Example:
public class Cat {
// ...
}
public class Dog {
// ...
}
The class which has a list reference with both types:
public class Person {
private List<Dog> dogs = Lists.newArrayList();
private List<Cat> cats = Lists.newArrayList();
// getters and setters which fire property change listeners.
}
And then i create the TreeViewer, and set the content provider:
treeViewer = new TreeViewer(parent);
IObservableFactory observableFactory = new IObservableFactory() {
public IObservable createObservable(final Object target) {
// target is a Person. What should I return here?
// If I return for example the observed dogs, cats wont be bound:
return BeanProperties.list("dogs").observe(target);
}
};
IContentProvider provider = new ObservableListTreeContentProvider(observableFactory, null);
treeViewer.setContentProvider(provider);
But because the factory can only return one IObservable, I can't observe both cats and dogs. How could i do that?
With your initial design, you can't do it. Why are dogs and cats on the same level in the tree? Levels usually contain same objects (because why would you put your cousins under your parents?).
OK, cats and dogs are both Animals, but then make them extending Animal class and use something like this:
class Person {
List<Animal> pets; // both dog and cats
}
IObservableFactory observableFactory = new IObservableFactory() {
public IObservable createObservable(final Object target) {
return BeanProperties.list("pets").observe(target);
}
};
And even this would not be a good idea, in case you want to display properties which are only related to cats, dogs, rabbits... .
I am not sure, why you want to use observable content provider (as usually Tree is convenient way to just display something). Wouldn't it be enough for you to use ITreeContentProvider? In this case you could stick with you model of having separate dogs and cats collections and do something like this:
class PetsContentProvider immplements ITreeContentProvider {
public boolean hasChildren(Object element) {
if (element instanceof Person) {
Person person = (Person) element;
return person.getCats().size > 0 || person.getDogs().size() > 0;
}
return false;
}
public Object getParent(Object element) {
// TODO: still better to have a common class
if((element instanceof Dog) || (element instanceof Cat)) {
// cast to dog or cat (or better animal)
// Animal pet = (Animal) element;
return pet.getOwner();
}
return null;
}
public Object[] getChildren(Object parentElement) {
if(parentElement instanceof Person) {
Person person = (Person) parentElement;
return person.getCats().toArray(); // and dogs
}
return EMPTY_ARRAY;
}
}
For more information, please see this very good article on JFace Trees.
And just traditionally Vogella's article on JFaceData Binding.
I have a method which i'd like to refactor
Basically i want to split the top level method in a abstract and a final part.
The method in question is overridden in quite a few places where additional functionality is added, but eventualy the super call is always made.
The code now basically look like:
(not all Extending classes override but those that do, do it this way)
class Base {
public Object getStuff(String key) {
out = //code to get data from the Database.
return out
}
class Extended1 extends Base {
public Object getStuff(String key) {
if("some_non_db_value".equals(key)) {
return "some custom stuff";
}
return super.getStuff(key);
}
}
What i'd like as a result would be something like:
class Base {
public final Object getStuff(String key) {
out = getCustom(key);
if(out != null) {
return custom;
}
out = //code to get data from the Database.
return out
}
public abstract Object getCustom(String key);
}
class Extended1 extends Base {
public Object getCustom(String key) {
if("some_non_db_value".equals(key)) {
return "some custom stuff";
}
return null;
}
}
I was hoping there would be a refactor action (or partial refactor) to get to (or closer to) this point.
I would first rename getStuff() to getCustom() which would take care of all the extended classes. Then changing the Base class should be relatively easy.