Should I subclass or use enum? - language-agnostic

I have many T arrays to read.
Each T array can represent data of type A, B or C.
A: A list of T
B: A single T
C: Exactly three T
When I read a T array, I will be able to get a list of T, and determine by reading the first T in the list whether it's of type A, B or C.
I thought of two possible approaches and would like to know their merits and cons.
1)
enum {A, B, C};
class X {
enum dataType;//A, B or C
List<T> data;//just store all as list of T
//other essential methods/properties
//throws exception if an instance cannot fit into either A, B or C.
X(T[] input)
{
//read input
}
}
2)
abstract class X
{
abstract int length{get;}
//and other common essential methods/properties
}
class A : X
{
List<T> data;
}
class B : X
{
T data;
}
class C : X
{
T data1, data2, data3;
}
class ConcreteX: X
{
List<T> data;
ConcreteX(T[] input)
{
//reads input and stores T(s) into data
}
}
class XFactory
{
getX(T[] input)
{
ConcreteX conX = new ConcreteX(input);
//depending on whether it's A, B or C, create an instance of A, B,
//or C and map the corresponding fields from conX to the instance.
//return that instance
}
}

In OOP the second way is more acceptable. The reason is, that if you would add behaviour depending on the type (A, B or C), in first case you would have to check for the enum value. In the second case, you add the specific behaviour to concrete types A, B and C. If you decided to add another type or remove one of them, in first case you would have to change all occourances of the type check, in the second case, change happens only in one place.

Well, if you need to have the generic class accept only a range of specific types then it might be easier to record the accepted types within an array. As you have not specified a specific language I will use c#, although I cannot guarantee it can be done with other lanaguages. I suppose if the language has the ability to at runtime create instances of the type they also should have the abilty to check against the type
private static List<Type> _acceptedTypes = { typeof(Type1), typeof(Type2) ... }
X(T[] input)
{
if(!_acceptedTypes.Contains(typeof(T)))
{
throw new SomeException();
}
...
}
Although personally this is not truely ideal as it is a runtime check (i.e. you only know about it when you try to use the class). It would be better to be able to apply constraints in a generic way which .net has but only against one type (which isn't helpful in your case).

Related

Convert an instance of QObject to JSON

I have some code that I am using to convert arbitrary QObject subclasses to JSON. I able to convert them if they are pointers to a subclass, but am curious whether it is possible to convert instances (provided the subclass implements a copy constructor). Is there some crazy way to use something like templates or the type information provided by QMetaType to copy an instance of a QObject subclass without knowing what it is? The ToJson code is in a class that has no knowledge of the subclass.
I think it might be possible with QMetaType::create or something similar but I haven't been able to figure out how to actually copy the properties of the subclass instance.
Here's my code for converting:
QJsonValue ToJson(QVariant value){
switch(value.type()){
case QVariant::Int:
case QVariant::Double:
return value.toDouble();
////Other cases, etc...
case QVariant::UserType:
QObject* obj_ptr = qvariant_cast<QObject*>(value);
if(obj_ptr) // value was originally a pointer to a QObject, works correctly
return ToJson(obj_ptr);
else { // value was orginally an instance of a QObject subclass
std::string t = value.typeName(); //returns "MyQObject"
int id = QMetaType::type(t.c_str()); //returns the id of the derived class
void* v = QMetaType::create(id, &value); //passing &value does nothing
obj_ptr = static_cast<QObject*>(v);
return ToJson(obj_ptr); //works, but resulting fields are all default
}
}
}
QJsonObject ToJson(QObject* o){
QJsonObject obj;
auto mo = o->metaObject();
for (int i = mo->propertyOffset(); i < mo->propertyCount(); ++i){
QVariant value = o->property(mo->property(i).name());
obj[mo->property(i).name()] = ToJson(value);
}
return obj;
}
Sample code use case:
qRegisterMetaType<MyQObject>();
MyQObject obj;
obj.db = 11.1;
QVariant test1 = QVariant::fromValue(obj);
QVariant test2 = QVariant::fromValue(&obj);
QJsonValue v1 = ToJson(test1); // default constructed values
QJsonValue v2 = ToJson(test2); // db = 11.1
Sample QObject subclass:
class MyQObject : public QObject {
Q_OBJECT
Q_PROPERTY(double DB MEMBER db)
Q_PROPERTY(int I MEMBER i)
public:
MyQObject();
MyQObject(const MyQObject& other) : QObject() {
i = other.i;
db = other.db;
}
int i = 50;
double db = 1.5;
};
Q_DECLARE_METATYPE(MyQObject)
Is there any way to handle the case illustrated by test1 above?
Long-story-short: nope. There is no way to store QObjects by value in containers or QVariant.
Qt forbids the copy of QObjects and all inheriting classes. The mandatory the Q_OBJECT macro will disable any copy constructor also in newly defined classes.
The copy constructor that you are defining in the MyObject class is missing the base class constructor call. If QObject had a copy constructor it would be something like this:
MyQObject(const MyQObject& other) :
QObject(other) // this will NEVER compile
{
i = other.i;
db = other.db;
}
Probably, the compiler is giving you a warning, but allows you to have such a constructor, even if it will result in undefined behavior or slicing an instance of MyObject every time it is passed by value.
Furthermore, the Qt docs states the following:
The values stored in the various containers can be of any assignable
data type. To qualify, a type must provide a default constructor, a
copy constructor, and an assignment operator. This covers most data
types you are likely to want to store in a container, including basic
types such as int and double, pointer types, and Qt data types such as
QString, QDate, and QTime, but it doesn't cover QObject or any QObject
subclass (QWidget, QDialog, QTimer, etc.).
So you can't store QObject and derived classes inside a Qt container unless you store them as pointers, as copy of QObjects is disabled by design.
Furthermore, if you want to exploit polymorphic behavior you must use pointers, even if there is no explicit need to cast to derived classes in your code, as far as I can see. If you really need to resort to casting in some place, you could consider making your ToJson a template function.
There is a solution, but use caution as it is only reasonable/applicable in the following scenario:
Classes in question are primarily data storage classes
The classes in question would be entirely copy-able if they didn't inherit from QObject
Most importantly, the ONLY reason you have the class inherit from QObject is so that it can have meta properties.
If your code uses the class as a QObject for any reason other than to get meta information, you are almost certainly using it incorrectly if you are trying to store it by value (as explained by G. Giordano in their answer).
Misuse considerations aside, in order to JSON-ify a QVariant that stores a QObject subclass by value, you can use the QMetaType::create method and pass it the user type id and yourQVariant.constData().
Example:
MyQObject obj;
obj.db = 11.1;
QVariant value = QVariant::fromValue(obj);
std::string t = value.typeName();
int id = QMetaType::type(t.c_str());
void* v = QMetaType::create(id, value.constData());
obj_ptr = static_cast<QObject*>(v);
QJsonValue json = ToJson(obj_ptr); //json contains db = 11.1

Liskov Substitute Principle (LSP) with Code example

Liskov Substitution Principle requires that
Preconditions cannot be strengthened in a subtype.
Postconditions cannot be weakened in a subtype.
Invariants of the supertype must be preserved in a subtype.
History constraint (the "history rule"). Objects are regarded as being modifiable only through their methods (encapsulation). Since subtypes may introduce methods that are not present in the supertype, the introduction of these methods may allow state changes in the subtype that are not permissible in the supertype. The history constraint prohibits this.
Can anybody please post an example violating each of these points and another example solving those?
All four items in the question have been thoroughly reviewed in this article.
Preconditions cannot be strengthened in a subtype.
This answer presents "real duck" and "electric duck" example, I suggest you go check it out. I'll use it in this item, for brevity.
It means that subtypes can't get in the way of how the original methods behaved in the base class. In the above mentioned answer's code, both ducks can swim, but the ElectricDuck will only swim if it's turned on. Therefore, any unit of code that requires that a duck (from the interface IDuck) swim now won't work, unless explicitly specified that the duck is ElectricDuck (and then turned on), which needs to be implemented everywhere.
Postconditions cannot be weakened in a subtype.
For this one, we can step back from the duck analogy. Let's take this answer as a base. Assume we have a baseclass that accepts only positive integers. If in a subtype, while extending the method, we remove the condition that the number must be positive, then all units of code that used to take for granted that the number was positive is now under risk of breaking, since now there's no guarantee that the number is positive. Here's a representation of this idea:
public class IndexBaseClass
{
protected int index;
public virtual int Index
{
get
{
//Will return positive integers only
return index < 0 ? 0 : index;
}
set
{
index = value;
}
}
}
public class IndexSubClass : IndexBaseClass
{
public override int Index
{
get
{
//Will pay no mind whether the number is positive or negative
return index;
}
}
}
public class Testing
{
public static int GetIndexOfList(IndexBaseClass indexObject)
{
var list = new List<int>
{
1, 2, 3, 4
};
return list[indexObject.Index];
}
}
If we call GetIndexOfList passing an IndexSubClass object, there's no guarantee that the number will be positive, hence potentially breaking the application. Imagine you're already calling this method from all over your code. You'd have to waste your time checking for positive values in all implementations.
Invariants of the supertype must be preserved in a subtype.
A parent class may have some invariants, that is, some conditions that must remain true for as long as the object exists. No subclass should inherit the class and eliminate this invariant, under the risk of all implementations so far breaking down. In the example below, the parent class throws an Exception if it's negative and then set it, but the subclass just plain ignores it, it just sets the invariant.
The following code was taken from here:
public class ShippingStrategy
{
public ShippingStrategy(decimal flatRate)
{
if (flatRate <= decimal.Zero)
throw new ArgumentOutOfRangeException("flatRate", "Flat rate must be positive
and non-zero");
this.flatRate = flatRate;
}
protected decimal flatRate;
}
public class WorldWideShippingStrategy : ShippingStrategy
{
public WorldWideShippingStrategy(decimal flatRate)
: base(flatRate)
{
//The subclass inherits the parent's constructor, but neglects the invariant (the value must be positive)
}
public decimal FlatRate
{
get
{
return flatRate;
}
set
{
flatRate = value;
}
}
}
History constraint (the "history rule").
This one is the same as the last rule. It states that the subtype should not introduce methods that mutate an immutable property in the parent class, such as adding a new Set method in a subclass to a property that once was only settable through the constructor.
An example:
public class Parent
{
protected int a;
public Parent(int a)
{
this.a = a;
}
}
public class Child : Parent
{
public Child(int a) : base(a)
{
this.a = a;
}
public void SetA(int a)
{
this.a = a;
}
}
Now, a previously immutable property in the parent class is now mutable, thanks to the subclass. That is also a violation of the LSP.
Do you know the ICollection interface?
Imagine you are writing a method that gets ICollection and manipulate it by using its Add method or better yet its Clear method
If someone passes an ReadOnlyCollection (that implements ICollection) you'll get an exception for using Add.
Now you would never expect that since the interface defines that is ok therefore the ReadOnlyCollection violated LSP.

Regarding variable initialization order

I'd like to know what's the default approach for those times when you need a variable to have been set in order for a given method/another variable initialization to work.
Like this:
Everything works if I initialize var A after var B. But not the other way around. I wrote the constructor, so I'll do that myself, but I'm not really sure where the code that tests for var B's existence should be. Or even if it should exist at all, for I have written the constructor and I initialize the values the order I see fit, but I feel it's a little insecure because it is not very robust in case anything changes.
Mind you, I'm talking about instance variables, if that helps.
FA
The answer can be influenced by the reason why a must be set before b.
Explicit Object Dependencies
If the reason is that b depends upon a, then the simplest thing to do is to make that dependency explicit at the time that b is created. For example, if a and b were objects then:
var a = new A(...);
var b = new B(a, ...);
var op = new Operation(b);
op.perform();
In this way, it is not possible to initialize the objects out of order. Note that A and B could be newly introduced wrapper objects that contain the original operation parameters.
Fluent Interface
If the reason is that the operation itself must know the value of a in order to perform some configuration in preparation for the arrival of b, then the operation constructor could be replaced by a fluent interface:
Operation op = Operation.withA(a).withB(b);
op.perform();
We must take care to define this fluent interface in such a way that withB can only be called after withA has been called. For example:
public class Operation {
private final C _c;
private final B _b;
private Operation(C c, B b) {
_c = c;
_b = b;
}
public static BStep withA(final A a) {
return new BStep() {
public Operation withB(B b) {
C c = setUpStateDependentUponA(a);
return new Operation(c, b);
}
};
};
public interface BStep {
Operation withB(B b);
}
public void perform() {
// do something with _c and _b
}
}
Here, C has been introduced to capture that state that is dependent upon a alone prior to the arrival of b. Note how the constructor of Operation is not visible to client code and that withB cannot possibly be called until after withA has been called.
I check before each time I access the variable, but if it is an instance variable and you initialize B in the constructor you should be safe. I use something like-
if (isset(var B)
{ do something with var A }
else
{ error handler }
or
try
{
if (isset(var B))
do something with a;
else
throw new Exception("attribute B has not been set.");
}
catch (Exception $e)
{
echo $e->getMessage();
return NULL;
}

Abstract syntax tree construction and traversal

I am unclear on the structure of abstract syntax trees. To go "down (forward)" in the source of the program that the AST represents, do you go right on the very top node, or do you go down? For instance, would the example program
a = 1
b = 2
c = 3
d = 4
e = 5
Result in an AST that looks like this:
or this:
Where in the first one, going "right" on the main node will advance you through the program, but in the second one simply following the next pointer on each node will do the same.
It seems like the second one would be more correct since you don't need something like a special node type with a potentially extremely long array of pointers for the very first node. Although, I can see the second one becoming more complicated than the first when you get into for loops and if branches and more complicated things.
The first representation is the more typical one, though the second is compatible with the construction of a tree as a recursive data structure, as may be used when the implementation platform is functional rather than imperative.
Consider:
This is your first example, except shortened and with the "main" node (a conceptual straw man) more appropriately named "block," to reflect the common construct of a "block" containing a sequence of statements in an imperative programming language. Different kinds of nodes have different kinds of children, and sometimes those children include collections of subsidiary nodes whose order is important, as is the case with "block." The same might arise from, say, an array initialization:
int[] arr = {1, 2}
Consider how this might be represented in a syntax tree:
Here, the array-literal-type node also has multiple children of the same type whose order is important.
Where in the first one, going "right"
on the main node will advance you
through the program, but in the second
one simply following the next pointer
on each node will do the same.
It seems like the second one would be
more correct since you don't need
something like a special node type
with a potentially extremely long
array of pointers for the very first
node
I'd nearly always prefer the first approach, and I think you'll find it much easier to construct your AST when you don't need to maintain a pointer to the next node.
I think its generally easier to have all objects descend from a common base class, similar to this:
abstract class Expr { }
class Block : Expr
{
Expr[] Statements { get; set; }
public Block(Expr[] statements) { ... }
}
class Assign : Expr
{
Var Variable { get; set; }
Expr Expression { get; set; }
public Assign(Var variable, Expr expression) { ... }
}
class Var : Expr
{
string Name { get; set; }
public Variable(string name) { ... }
}
class Int : Expr
{
int Value { get; set; }
public Int(int value) { ... }
}
Resulting AST is as follows:
Expr program =
new Block(new Expr[]
{
new Assign(new Var("a"), new Int(1)),
new Assign(new Var("b"), new Int(2)),
new Assign(new Var("c"), new Int(3)),
new Assign(new Var("d"), new Int(4)),
new Assign(new Var("e"), new Int(5)),
});
It depends on the language. In C, you'd have to use the first form to capture the notion of a block, since a block has a variable scope:
{
{
int a = 1;
}
// a doesn't exist here
}
The variable scope would be an attribute of what you call the "main node".
I believe your first version make more sense, for a couple of reasons.
Firstly, the first more clearly demonstrates the "nestedness" of the program, and also is clearly implemented as a rooted tree (which is the usual concept of a tree).
The second, and more important reason, is that your "main node" could really have been a "branch node" (for example), which can simply be another node within a larger AST. This way, your AST can be viewed in a recursive sense, where each AST is a node with other ASTs as it children. This make the design of the first much simpler, more general, and very homogeneous.
Suggestion: When dealing with tree data structures, wheter is compiler-related AST or other kind, always use a single "root" node, it may help you perform operations and have more control:
class ASTTreeNode {
bool isRoot() {...}
string display() { ... }
// ...
}
void main ()
{
ASTTreeNode MyRoot = new ASTTreeNode();
// ...
// prints the root node, plus each subnode recursively
MyRoot.Show();
}
Cheers.

Do I need to use dynamic_cast when calling a function that accepts the base class?

I have some classes like this:
interface class IA
{
};
interface class IB
{
};
public ref class C : public IA, public IB
{
};
public ref class D
{
void DoSomething(IA^ aaa)
{
}
void Run()
{
C^ bob = gcnew C();
DoSomething(dynamic_cast<IA^>(bob)); // #1
DoSomething(bob); // #2
}
};
At the moment I always try to use dynamic casting when calling such a function, (the #1 above).
However it does make the code quite ugly, so I want to know if it is actually necessary.
Do you use dynamic_cast in this way? If so what is the main reason?
In standard C++, you use dynamic_cast to walk down the hierarchy, not up. In this case, you'd use it to try and convert an IA or IB into a C:
IA^ temp = /* get a C in some way. */;
C^ tempC = dynamic_cast<C^>(temp);
Since we know bob is of type C^, we know at compile time it can be downcasted to IA^ safely, and so dynamic_cast is equivalent to static_cast here. Moreover, the implicit cast you propose is also safe.
dynamic_cast is only needed when upcasting from a base type to a derived.
No, I would think that in C++/CLI you also don't need the dynamic cast here. Derived* implicitly converts to Base* unless there's an ambiguity w.r.t. multiple inheritance. The same it probably true for "gc-pointers". In C++ a dynamic cast -- when upcasting -- requires polymorphic classes (with at least one virtual function). I don't know how C++/CLI handles it, though. I would think every CLI class is by default polymorphic.
You may want to remove the C++ tag, by the way. ;)