Subclass to only replace constructor vs function that generates an instance - oop

Given a class A and a group of instances B that are created in the same way but have no extra functionallity to the class.
What would be the better pattern
subclassing A overriding only the constructor
or have a function that creates instances of group B
e.g.
class A
{
int x;
int y;
}
option A:
class B
{
constructor()
{
super(0,random())
}
}
option B:
createB()
{
return new A(0,random())
}
EDIT:
class B constructor should've been using super

The better approach is definitely not to create additional functions.Constructors are meant for that and you should not move the logic away.
Rethink if you really need B class. Because if you don't, the whole code can be simplified to:
class A {
int x;
int y;
public A() {
x = 0;
y = Math.random();
}
public A(int x, int y) {
this.x = x;
this.y = y;
}
}
In most of the languages, constructors can be overloaded based on the number and types of parameters.
If you really need B class, I suggest simply calling super constructor:
class A {
int x;
int y;
public A(int x, int y) {
this.x = x;
this.y = y;
}
}
class B extends A {
public B() {
super(0, Math.random());
}
}
I am not sure what do you mean by "instances were created in the same way", but with OOP you can instantiate parent class with an instance of a child, e.g.:
A a = new A(10,20);
A b = new B();

It's better to use option B.
This is a classic pattern, named Fabric Method in fundamental book Gang of Four.

Related

Different constructor signature for derived class

Is it break oop principles (ex, Liskov principle), if constructor signature for derived class is not the same as base class?
class Base {
protected x: number;
protected y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
class Derived extends Base {
private text: string;
constructor(text: string, x: number, y: number) {
super(x, y);
this.text = text;
}
}
No it does not, because Liskov principle talks about "contravariance of method arguments and return types in the subtype". When you do something like this:
foo(bar:Base){
//do stuff
}
this method expects an instance of Base class, not a constructor so the contravariance of methods does not apply to this case.
It would break this principle if you did something like this, because a Base instance could not be replaced by an Extended one :
class Base{
foo():string{
return "";
}
bar(arg:string){}
}
class Extended extends Base{
foo():number{
return 1;
}
bar(arg:boolean){}
}
But this is not allowed by the typescript compiler.

How do you create a class in Wollok?

I want to know if it's possible to define a class with some sort of constructor or if I have to initialize every field by hand.
Constructors in wollok are defined using the 'constructor' keyword. For example:
class Point {
var x
var y
constructor(_x, _y) {
x = _x
y = _y
}
}

superclass accesing methods of a sublass in oop

I was wondering, is it possible that a superclass to access the methods of a inherited subclass, like for example in Java?
I know that a subclass can override and even implements, in case of abstract classes, the methods of the superclass, but the question mentioned above is possible?
Thanks
Example in c#.. in superclass make abstract method, which is implemented in derived class
public abstract class SuperCLass
{
public void CallSubMethod()
{
Test(); // calls method in derived class
}
public abstract void Test();
}
public class SubClas : SuperCLass
{
public override void Test()
{
// code here
}
}
Java, PHP, Ruby, Python, C# (and so on) methods are always virtual, so, no matter what, when you override a method in a subclass, this version will be called:
public class SuperClass {
public void someMethod() {
otherMethod();
}
public void otherMethod() {
System.out.println("Super");
}
}
public class SubClass extends SuperClass {
public void otherMethod() {
System.out.println("Sub");
}
}
SubClass o1 = new SubClass();
o1.someMethod(); // Outputs: Sub
SuperClass o2 = new SubClass();
o2.someMethod(); // Also outputs: Sub
So, you not just CAN access your subclass method, you HAVE TO.
Just for comparison, in C++, for example, things work different. If you don't declare a method as virtual, you can't override it.
I' ll try to explain as they explained to me at university.
You have a reference:
Object o = new Object()
His static type(ST) is Object : this is his own type and never changes.
His dynamic type(DT) is also Object(in this case): the reference point to an object of type Object, but it can change.
for example if i write :
Object o = new String("abc") // now his ST == Object but the DT == String
That being said:
Upcasting is always permitted: consider two references s and r. the assignment s=r compile and execute always if ST(r) <= ST(s) (the static type of r is, in the hierarchi, less or equals to the static type of s)
for example:
class A { }
class B extends A { }
...
A a = new A(); B b = new B();
a = b // OK, upcast
Downcasting: at compile-time it is always legal to downcast from a type X to a type Y if X and Y belong to hierarchy.
Consider the reference s. I want to cast s to a type C, so if C <= TS(s) it will always compile if I do the cast as : C r = (C)s
for example:
class A { }
class B extends A { }
class C extends A { }
...
A a = new A(); B b = new B();
C c = new C();
...
b = c // ILLEGAL
b = (B)a // OK at compile-time but maybe at run-time it is not!
When we run our application if the downcast fails, Java raise an Exception.
Otherwise it success.
To downcast correctly:
consider a reference ref and we want to cast to a type C. So a downcast will success if DT(ref) <= C <= ST(ref) .
And the downcast will be obtained as: C ref2 = (C)ref
for example:
// I suggest to write the hierarchy in a piece of paper and
// try the rules before coding.
class A { }
class B extends A { }
class C extends A { }
class D extends B { }
...
A a = new A(); B b = new B();
C c = new C(); D d = new D();
A r = new B();
A s = new D();
a = b; // OK, upcast
a = d; // OK, upcast
/* b = c; */ // ILLEGAL
b = (B)r; // OK, downcast
d = (D)r; // downcast: it compiles, but fails at run-time
d = (D)s; // OK, downcast
/* b = s; */ // ILLEGAL
/* d = (D)c; */ // ILLEGAL
b = (B)s; // OK, downcast
b = (D)s; // OK, downcast
PS: please forgive if I made some mistake but I wrote a bit in a hurry.
In Java, It's not possible, and I think what you are asking would go against OOP.

OOP question involving the best way to reference a base class protected variable without having to typecast every-time it is used

I have a quick OOP question and would like to see how others would approach this particular situation. Here it goes:
Class A (base class) -> Class B (extends Class A)
Class C (base class) -> Class D (extends Class C)
Simple so far right? Now, Class A can receive an instance of Class C through its constructor. Likewise, Class B can receive an instance of either class C or Class D through its constructor. Here is a quick snippet of code:
Class A
{
protected var _data:C;
public function A( data:C )
{
_data = data;
}
}
Class B extends A
{
public function B( data:D )
{
super( data );
}
}
Class C
{
public var someVar:String; // Using public for example so I don't need to write an mutator or accessor
public function C() { } // empty constructor for example
}
Class D extends C
{
public var someVar2:String; // Using public for example so I don't need to write an mutator or accessor
public function D() { super(); } // empty constructor for example
}
So, let's say that I am using class B. Since _data was defined as a protected var in Class A as type C, I will need to typecast my _data variable to type D in class B every time I want to use it. I would really like to avoid this if possible. I'm sure there is a pattern for this, but don't know what it is. For now, i'm solving the problem by doing the following:
Class B extends A
{
private var _data2:D;
public function B( data:D )
{
super( data );
_data2 = data;
}
}
Now, in class B, I can use _data2 instead of typecasting _data to type D every-time I want to use it. I think there might be a cleaner solution that others have used. Thoughts?
I think B doesn't take C or D... in order for it to do what you wrote it should be
public function B( data:C )
{
super( data );
}
At least as far as I used to know :)
I doubt you can use a downwards inheritance in your case.
As for the pattern, the best one to use in situations like these is Polymorphism. Alternatively, depending on language, you can use interfaces. Or if languages allow it, even a combination of conventional code and templates.
Most modern OO languages support covariant of return type, that is: an overriding method can have a return type that is a subclass of the return type in the original (overridden) method.
Thus, the trick is to define a getter method in A that will return C, and then have B override it, such that it returns D. For this to work the variable _data is immutable: it is initialized at construction time, and from that point it does not change its value.
Class A {
private var _data:C;
public function A(data:C) {
_data = data;
}
public function getData() : C {
return _data;
}
// No function that takes a C value and assigns it to _data!
}
Class B extends A {
public function B(data:D) {
super(data);
}
public function getData() : D { // Override and change return type
return (D) super.getData(); // Downcast only once.
}
}
This how I usually write it in Java:
public class A {
private final C data;
public A(C data) { this.data = data; }
public C getData() { return data; }
}
public class B extends A {
public B(D data) { super(data); }
#Override
public D getData() { return (D) super.getData(); }
}

Method and mock with same class

I have class with 2 methods
class A
{
void Fun()
{
if(FunRet()>0){///} else {///}
}
int FunRet()
{ return 4;}
};
I want to test Fun() method depend on what FunRet returns. So i want to mock FunRet.
I rather don't want make FunRet as virtual. How I can do that?
You can inject intra-class dependencies. In this case, make Fun accept a value instead of computing it:
class A
{
void Fun(int x)
{
if(x>0){///} else {///}
}
int FunRet()
{ return 4;}
};
Then your tests can pass arbitrary values into Fun(). If you need to enforce correct use, write a public version to expose in your API and a private version for testing:
class A {
public:
void Fun() { return Fun(FunRet()); }
private:
void Fun(int x); // for testing.
};
You could extract the Fun method into a calculator class that implements an interface. You should pass an instance of that interface to class A at constructor.
In testing you could have other classes implementing that interface, that return other values.
This method also have the big advantage, that you seperate the concerns of calculating a value and using the calculated value.
class A {
public:
A (IFunCalc calc) { m_calc = calc; }
void Fun { if calc.FunRet() > 4 ... }
private:
IFunCalc m_calc;
}
class FunCalc : IFunCulc {
public:
int FunRet { return 4; }
}
class FunCalc4Test : IFunCalc {
public:
int FunRet { return 27; }
}
I think you're missing the this pointer.
... if ( this->FunRet() > 0 ) { ...
If you use dependency injection and template your object under test, you can use mock objects without having to use virtual functions.
class AParameters
{
public:
int FunRet()
{ return 4;}
};
class MockAParameters
{
public:
MOCK_METHOD0(FunRet, int());
};
template<class Parameters>
class AImpl
{
public:
AImpl(Parameters& parameters):parameters(parameters){}
void Fun()
{
if(parameters.FunRet()>0){///} else {///}
}
private:
Parameters& parameters;
};
typedef AImpl<AParameters> A;
typedef AImpl<MockAParameters> ATestObject;
void Test::funUsesFunRet()
{
MockAParameters params;
EXPECT_CALL(params, FunRet());
ATestObject object(params);
object.Fun();
}
I believe FunRet is an internal implementation detail of Fun. As a result, Fun does not need to be tested in isolation from FunRet. Just test Fun and don't worry about the fact it calls FunRet.