(This example written by Typescript but not only in Typescript case)
class IMyInterface {
doC:(any) => any;
}
class Common {
commonProperty:any;
doA() {
}
doB() {
}
}
class ClassA extends Common {}
class ClassB extends Common implements IMyInterface {
doC(test:any) {
return true;
}
}
class Factory {
myClass: Common;
doSomething() {
// Property 'doC' does not exist on type 'Common'
this.myClass.doC('test');
}
}
Class A and B are extended Common class, so that in Factory class can define myClass type as Common.
But Class B need to implement IMyInterface, which Common class doesn't contained. So the Factory class throws an error that the interface method is not existed on Common class.
How and what's the best way to solve this?
[Edited]
First of all, #basarat thank you very much, but I'm still curious a little,
What if there are some more classes which implements IMyInterface
class ClassC extends Common implements IMyInterface {
doC(test:any) {
return true;
}
}
class ClassD extends Common implements IMyInterface {
doC(test:any) {
return true;
}
}
class ClassE extends Common implements IMyInterface {
doC(test:any) {
return true;
}
}
In that case, I can think, I can define the doC() method in Common class.
But also I want to make ClassB, C, D and E must implement the Doc method.
please advise me,
How and what's the best way to solve this
You basically want to say that myClass is generally just Common but in a special case it might be ClassB. You can do this using a union type + using a typeguard:
class Factory {
myClass: Common | ClassB;
doSomething() {
const myClass = this.myClass;
if (myClass instanceof ClassB){
// works!
myClass.doC('test');
}
}
}
More
Complete example:
class IMyInterface {
doC:(any) => any;
}
class Common {
commonProperty:any;
doA() {
}
doB() {
}
}
class ClassA extends Common {}
class ClassB extends Common implements IMyInterface {
doC(test:any) {
return true;
}
}
class Factory {
myClass: Common | ClassB;
doSomething() {
const myClass = this.myClass;
if (myClass instanceof ClassB){
// works!
myClass.doC('test');
}
}
}
Docs
Union type : https://basarat.gitbooks.io/typescript/content/docs/types/type-system.html#union-type
Type Guard: https://basarat.gitbooks.io/typescript/content/docs/types/typeGuard.html
UPDATE
As requested, if one does want to test for the interface one needs to create a user defined type guard (docs https://basarat.gitbooks.io/typescript/content/docs/types/typeGuard.html#user-defined-type-guards). Example:
function isMyInterface(foo:any): foo is IMyInterface {
return typeof foo.doC === 'function';
}
class Factory {
myClass: Common | IMyInterface;
doSomething() {
const myClass = this.myClass;
if (isMyInterface(myClass)){
// works!
myClass.doC('test');
}
}
}
So complete code becomes :
class IMyInterface {
doC:(any) => any;
}
class Common {
commonProperty:any;
doA() {
}
doB() {
}
}
class ClassA extends Common {}
class ClassB extends Common implements IMyInterface {
doC(test:any) {
return true;
}
}
class ClassC extends Common implements IMyInterface {
doC(test:any) {
return true;
}
}
class ClassD extends Common implements IMyInterface {
doC(test:any) {
return true;
}
}
class ClassE extends Common implements IMyInterface {
doC(test:any) {
return true;
}
}
function isMyInterface(foo:any): foo is IMyInterface {
return typeof foo.doC === 'function';
}
class Factory {
myClass: Common | IMyInterface;
doSomething() {
const myClass = this.myClass;
if (isMyInterface(myClass)){
// works!
myClass.doC('test');
}
}
}
Related
I have a Parent class written in Java file
public class ParentClass {
public static int method1() {
return 1;
}
}
I have a Child class written in kotlin
class ChildClass: ParentClass() {
companion object {
#JvmStatic
fun childMethod1(): Int {
return 100
}
}
}
Similarly, I have a child class written in Java
class JavaChildClass extends ParentClass {
public static int childMethod1() {
return 200;
}
}
Now, in my main kotlin class, I am trying to access the methods,
val result1 = JavaChildClass.childMethod1() //Method in the Java child class
val result2 = JavaChildClass.method1() //Method in the parent class
val result3 = ChildClass.childMethod1() //Method in Kotlin Child class
val result4 = ChildClass.method1() //Error, cannot access this method
Say i have a code as follows
interface Interface1
{
void method1();
}
interface Interface2
{
void method2();
}
class ClassWithInterfaces : Interface1,Interface2
{
void method1(){}
void method2(){}
}
Now in my "manager" class i implement this as follows :
public OtherClass
{
Interface1 interface1;
Interface2 interface2;
public void someMethod()
{
ClassWithInterfaces classWithInterfaces = new ClassWithInterfaces();
interface1 = classWithInterfaces;
interface2 = classWithInterfaces
}
}
I don't feel that this is the right way to do it hovewer i can't come up with other solutions i can't use Dependency Injection Frameworks in my project if you ask about that. Can you tell me wheter apart from DI there is a better way of doing that?
Hello and welcome to Stack Overflow :-)
You don't have to use a framework in order to do DI. In fact, there are some languages that make it impossible to use a framework for DI - e.g., C++.
Any way, in your case, the proper way to do DI is like this:
interface Interface1
{
void method1();
}
interface Interface2
{
void method2();
}
interface Interface3 : Interface1, Interface2
{
void method1();
void method2();
}
class ClassWithInterfaces : Interface3
{
void method1(){}
void method2(){}
}
public OtherClass
{
Interface3 m_interface3;
OtherClass(Interface3 interface3)
{
m_interface3 = interface3;
}
public void someMethod()
{
m_interface3.method1();
m_interface3.method2();
}
}
// And now the usage:
public main()
{
ClassWithInterfaces classWithInterfaces = new ClassWithInterfaces();
OtherClass otherClass = new OtherClass(classWithInterfaces);
}
My question is, how to redesign abstract factory.
For example, I get next abstraction of vehicles:
interface IEngine { int Power(); }
class Gasoline : IEngine { public int Power() {return 150; }}
class Diesel : IEngine { public int Power() { return 50; }}
interface IFrame { string Name(); }
class Boxed : IFrame { public string Name() { return "Boxed frame"; }}
class Hat : IFrame { public string Name() { return "Hat frame"; }}
interface TransportFactory {
IEngine CreateEngine();
IFrame CreateChassis();
}
class TrailerCar : TransportFactory {
public IEngine CreateEngine() { return new Diesel(); }
public IFrame CreateChassis() { return new Boxed(); }
}
class PrivateCar : TransportFactory {
public IEngine CreateEngine() { return new Gasoline(); }
public IFrame CreateChassis() { return new Hat(); }
}
Now, I can instantiate private or trailer car.
Some one suggest me changes: engine for trailers cars can by turbo or hybrid. Only for trailers! For private car diesel and gasoline engines still usual diesel engine.
So, if i do changes:
public enum EngineType { Hybrid, Turbo, }
interface TransportFactory
{
IEngine CreateEngine(EngineType t);
IFrame CreateChassis();
}
and i can add classes:
class GasolineHybrid : IEngine
{
public int Power()
{
return 70;
}
}
class GasolineTurbo : IEngine
{
public int Power()
{
return 170;
}
}
class DieselHybrid : IEngine
{
public int Power()
{
return 60;
}
}
class DieselTurbo : IEngine
{
public int Power()
{
return 98;
}
}
it is good, but (!!!) private car nothing to do with it!!!
What kind of design can i use? Old abstraction get incorrect?
Thanks a lot!!!
How about:
class GasolineHybridTrailerCar : TransportFactory
{
public IEngine CreateEngine()
{
return new GasolineHybrid();
}
...
}
class GasolineTurboTrailerCar : TransportFactory
{
public IEngine CreateEngine()
{
return new GasolineTurbo();
}
...
}
class DieselHybridTrailerCar : TransportFactory
{
public IEngine CreateEngine()
{
return new DieselHybrid();
}
...
}
class DieselTurboTrailerCar : TransportFactory
{
public IEngine CreateEngine()
{
return new DieselTurbo();
}
...
}
The idea behind spawning numerous classes is to remove client's ability to do wrong choice. Since you said hybrid and turbo engines do not make sense for private cars, then keeping
IEngine CreateEngine(EngineType t);
will require from private car factory additional efforts to refuse incorrect arguments.
I am not sure did you mean it, but class names suggest that cars are products of factory. In classic relation it will be factory --produce--> product. It is kinky and fun how you put it via generalization, but could be hardly recognizable by others. The beauty of patterns is that once you hear its one word name, then you feel confident about all the internals the implementation could imply.
There is pattern Builder. Would it be more suitable name for your design?
Remember that parameters need not be part of the interface, they can be passed to the constructor of the implementation. So you can still keep your old interface:
interface TransportFactory
{
IEngine CreateEngine();
IFrame CreateChassis();
}
but pass the EngineTypeto the TrailerCar constructor:
class TrailerCar : TransportFactory {
private readonly EngineType engineType;
public TrailerCar(EngineType engineType)
{
this.engineType = engineType;
}
public IEngine CreateEngine()
{
if (engineType == EngineType.Hybrid) return new DieselHybrid();
else return new DieselTurbo();
}
public IFrame CreateChassis() { return new Boxed(); }
}
I have a 1-to-many relationship between the RestorableEnvironment and IBaselineEntity objects: a given RestorableEnvironment will have one and only one IBaselineEntityobject, but each IBaselineEntity object may be tied to 0-n RestorableEnvironment objects. However, IBaselineEntity is implemented in one of two ways: via a file or via a database. My classes are (generally) like:
public interface IBaselineEntity
{
BaselineImage BuildImage();
//Remainder of interface
}
public class BaselineFile : IBaseline
{
//implementation
}
public class BaselineDatabase : IBaseline
{
//implementation
}
public class RestorableEnvironment
{
public IBaselineEntity BaselineEntity { get; set; }
//Remainder of class
}
NHibernate needs the concrete implementation of the IBaselineEntity in the references statement. To handle that, I have updated RestorableEnvironment to:
public class RestorableEnvironment
{
public IBaselineEntity BaselineEntity
{
get { return BaselineDatabase ?? BaselineFile; }
set
{
BaselineFile = value as BaselineFile;
BaselineDatabase = value as BaselineDatabase;
}
}
private BaselineFile _baselineFile;
public BaselineFile BaselineFile
{
get { return _baselineFile; }
protected set
{
_baselineFile = value;
if (value != null)
BaselineDatabase = null;
}
}
private BaselineDatabase _baselineDatabase;
public BaselineDatabase BaselineDatabase
{
get { return _baselineDatabase; }
protected set
{
_baselineDatabase= value;
if (value != null)
BaselineFile = null;
}
}
// Remainder of class
}
Now that I have concrete classes, I can now map in NHibernate, but this feels like a hack. Are there any suggestions for an improvement?
map it as any reference
using fluentmapping
// ClassMap<RestorableEnvironment>
RestorableEnvironmentMap()
{
ReferenceAny(e => e.BaselineEntity)
.EntityIdentifierColumn("entirtyid")
.EntityTypeColumn("entitytype")
.IdentityType<int>()
.MetaType<string>()
.AddMetaValue<E1>("e1")
.AddMetaValue<E2>("e2");
}
Consider the following 2 methods:
class A{
void Method1(){
if(!something) return;
DoX();
DoY();
DoZ();
}
class B{
void Method2(){
if(!something) return;
DoX();
DoY();
DoP();
}
}
obviously a superclass could be written to avoid dry principle:
class Super{
virtual void Method(){
if(!something) return; //problem...
DoX();
DoY();
}
}
class A:Super{
override void Method(){
inherited Method();
DoZ();
}
}
class B:Super{
override void Method(){
inherited Method();
DoP();
}
}
The problem is the !something check where it would run out in the first example whereas in the second, it will run out of the super class's method, but do either DoZ() or DoP() in the derived class;
My question: What is the best way to solve this kind of problem? The one that comes to my hand is making the super class's method a function that returns bool
virtual bool Method(){ if(!something) return false;}
override bool Method(){ if(!inherited Method()) return;}
is this the best workaround?
How about:
class Super {
void Method() {
if (!something) return;
DoX();
DoY();
DoThingy();
}
abstract void DoThingy();
}
class A : Super {
override DoThingy() {
DoZ();
}
}
class B : Super {
override DoThingy() {
DoP();
}
}
Why not declaring another virtual method for DoP or Doz, you can wrap them if you want to keep them public with their respective names.
Like superclass :
virtual void wrapping(){};
Then each child :
void wrapping() { DoP(); }
void wrapping() { DoZ(); }
Don't know if I've been clear.
Another option: Keep the checks in the derived methods. Maybe a derived class might need a slightly different condition?
class Super{
virtual void Method(){
DoX();
DoY();
}
}
class A:Super{
override void Method(){
if(!something) return;
inherited Method();
DoZ();
}
}
class B:Super{
override void Method(){
if(!something) return;
inherited Method();
DoP();
}
}