I have the following abstractFactory class:
class virtual virtualProductA = {
pub virtual methodA: string;
};
class virtual virtualProductB = {
pub virtual methodB: int;
};
class virtual abstractFactory = {
pub virtual createProductA : virtualProductA;
pub virtual createProductB : virtualProductB;
};
In particular, I would like to specify that the abstractFactory createProductA method has an optional param, that can be of any type.
Something along the lines of the following:
pub virtual createProductA (param?:any) : virtualProductA;
However, the above does not compile properly.
Any suggestions as to proper syntax is more than greatly appreciated. Thank you.
Disclaimer: I'm using OCaml. The Reason examples are translated using Try Reason.
I'm not sure I got your question right, but here are my thoughts on this.
If you want to give an argument to the constructor of your class virtualProductA, here the syntax.
OCaml
class virtual virtualProductA my_object = object
val value : 'a = my_object
method virtual methodA : string
end
Reason
class virtual virtualProductA my_object => {
as _;
val value: 'a = my_object;
pub virtual methodA: string;
};
In your abstract factory, the method createProductA now takes an argument and is polymorphic.
OCaml
class virtual abstractFactory = object
method virtual createProductA : 'a. 'a -> virtualProductA
method virtual createProductB : virtualProductB
end
Reason
class virtual abstractFactory = {
as _;
pub virtual createProductA: 'a. 'a => virtualProductA;
pub virtual createProductB: virtualProductB;
};
The type quantifier 'a. means "for all types 'a, ...". It is used to tell the compiler "This is not a type parameter, this is merely a polymorphic method".
On second thought, you will probably want to make virtualProductA generic, here's the syntax for that:
OCaml
class virtual ['a] virtualProductA my_object = object
val value : 'a = my_object
method value = value (* type 'a is inferred here, no need to over-annotate *)
method virtual methodA : string
end
Reason
class virtual virtualProductA 'a my_object => {
as _;
val value: 'a = my_object;
pub value = value; /* type 'a is inferred here, no need to over-annotate */
pub virtual methodA: string;
};
Related
Let suppose, I have an interface Animal, it has two implementations: Dog and Cat, and we have some method for this class:
fun Animal.sound() : String {
if (this is Dog) return "woof"
if (this is Cat) return "meow"
return "globglogabgalab"
}
Then, I want to test all cases of this method
How can I do that (with JUnit/Mockito), if I don't have an implementation for default behavior?
You could use kotlins Sealed classes in combination with a when statement, then you wouldn't need the last return statement, because that would statement would be unreachable.
sealed class Animal
class Dog : Animal()
class Cat : Animal()
and the sound method would look like this.
fun Animal.sound() = when (this) {
is Cat -> "meow"
is Dog -> "woof"
}
Alternatively, without sealed classes you could just create a TestAnimal implementation, which implements Animal in your tests, then instantiate it and run the sound() method.
class TestAnimal : Animal
#Test
fun foo() {
TestAnimal().sound()
}
or with a anonymous implementation
#Test
fun foo() {
val animal = object : Animal {}
animal.sound()
}
I have a class with some (not pure) virtual functions which I use as a base type for other classes:
struct abstract_object {
...
}
in some of my other classes I need this tailed method:
struct Int : public abstract_object {
/*virtual*/auto sum(Int* v) -> decltype(*this + *v) { return *this + *v; }
}
in all honesty, I don't know if this is legal, but, can I write a virtual version for the method in the base class? Until now I failed to find the right signature. c++11 is all I can stretch to.
Thanks for your help
Currently I am working on a compiler for a C/C++ like language to be more specific a typechecker.
I have generated a parser with a grammar and the bnfc tool. For my typechecker I need to infer the type of expressions. All expressions are derived from a abstract base class Exp like the following:
class Exp {
...
}
class ExpPlus : public {
...
}
class ExpAnd : public {
...
}
...
ExpPlus refers to Exp + Exp and ExpAnd to Exp && Exp respectively.
My infer function takes a Expression and returns it's type and looks like this:
ype *TypeChecker::infer(Exp *exp)
{
// check for kind of expression
/* Base cases */
if(dynamic_cast<ETrue*>(exp))
{
Type *tBool = new Type_bool;
return tBool;
}
if(dynamic_cast<EFalse*>(exp))
{
Type *tBool = new Type_bool;
return tBool;
}
if(dynamic_cast<EInt*>(exp))
{
Type *tInt = new Type_int;
return tInt;
}
if(dynamic_cast<EDouble*>(exp))
{
Type *tDouble = new Type_double;
return tDouble;
}
if(dynamic_cast<EId*>(exp)) // search for type of given Id in contexts
{
EId *eId = dynamic_cast<EId*>(exp);
Type *typeOfSearchedId = env_->lookupVarTypeFromContext(eId->id_);
return typeOfSearchedId;
}
/* Base cases end*/
/* check expressions */
if(dynamic_cast<EApp*>(exp))
{
EApp *eApp = dynamic_cast<EApp*>(exp);
Type *retType = env_->lookupFunTypeFromSymbolTable(eApp->id_).returnType;
return retType;
}
if(dynamic_cast<EUPlus*>(exp))
{
// cast exp to type of exp
EUPlus *eu_plus = dynamic_cast<EUPlus*>(exp);
// infer till base case is derived
Type *typeExp = infer(eu_plus->exp_);
// if type is int or double
if(dynamic_cast<Type_int*>(typeExp) || dynamic_cast<Type_double*>(typeExp))
return typeExp;
throw TypeException("Trying to unary add wrong type: " + env_->getStringRepresentationOfType(typeExp));
}
...
As you can see I have a long list of If-statements that checker of which concrete expression type the expression is, it works fine and stuff but I wonder whether there is any more elegant way of doing this.
You got polymorphism the wrong way around.
Instead of this:
class Base {};
class Derived1 : public Base {};
class Derived2 : public Base {};
class Derived3 : public Base {};
//...
void foo(Base* b) {
if(dynamic_cast<Derived1*>(b)) {
do_something( dynamic_cast<Derived1*>(b));
} else if (dynamic_cast<Derived2*>(b)) {
do_something( dynamic_cast<Derived2*>(b));
} else if ....
}
You should acutally make use of polymorhism by using virtual methods:
class Base {
virtual void do_something() = 0;
virtual ~Base() {}
};
class Derived1 : public Base {
void do_something() override { /*...*/ }
};
class Derived2 : public Base {
void do_something() override { /*...*/ }
};
//...
void foo(Base* b) {
b->do_something();
}
Note how now not every method that uses Base* and expects different behavior depending on the dynamic type must actually know the dynamic type. foo just calls do_something and virtual dispatch selects the right method to be called. If you write some bar(Base*) you do not need a second block of if-else but rather call virtual methods again.
I simplified the example a lot, though it seems like in your code all branches return a type and the only difference is different implementations for different derived classes.
I have hierarchy of classes:
class A
{
};
class B : public A
{
};
class C : public B
{
};
class D : public A
{
};
and I have some function, which performs notification:
void notify(A* sender, const NotificationType notification)
{
}
My problem is how to find out exact type of sender object. I want to find elegant way to solve this problem. I don't like to use dynamic cast for these purposes. Possible way is to define enum within class A like:
enum ClassType
{
CLASS_A,
CLASS_B,
CLASS_C,
CLASS_D
};
and defining virtual method:
virtual ClassType get_type(void) const;
But this approach has bad scalability. Another way to keep this information in NotificationType, but it has bad scalability too.
P.S. I just want to use similar code:
I want to use similar code:
void notify(A* sender, const NotificationType notification)
{
if (sender is object of A)
new GuiA();
else if (sender is object of B)
new GuiB();
else if (sender is object of C)
new GuiC();
else
new GuiD();
}
To create a matching GUI object based on the concrete type of sender, you could pass a factory to some kind of factory method in A.
class A
{
public:
virtual Agui* createGui(GuiFactory& fac) = 0;
};
class GuiFactory
{
public:
virtual Agui* forB(B&) = 0;
virtual Agui* forC(B&) = 0;
virtual Agui* forD(D&) = 0;
};
class B : public A
{
public:
Agui* createGui(GuiFactory& fac)
{
return fac.forB(*this);
}
};
void notify(A* sender, const NotificationType notification)
{
// Use A interface...
// Get the concrete GuiFactory from somewhere, and use it
auto gui = sender->createGui(win32GuiFactory);
}
If you want know type to persist your hierarchy, conside to use boost::TypeIndex (http://www.boost.org/doc/libs/develop/doc/html/boost_typeindex.html).
If you want know type to process different types in different manners, conside to use Visitor insted of type identifier or make abstract interface with virtual functions covers your needs.
EDITED
Your goal is to create different UI object for different types. You can use the following model to reach your goal:
class UIObject {...};
class UIObjectFactory {...};
class A {
public:
virtual std::unique_ptr<UIObject> Create(UIObjectFactory& factory) = 0;
};
void OnNotify(A* sender) {
auto ptr = sender->Create(GetUIFactory());
...
}
and defining virtual method:
virtual ClassType get_type(void) const;
The easiest way to achieve this and get rid of scalability issue is to implement your get_type() member function in each class A, B, C, ... this way:
typedef uintptr_t ClassType;
virtual ClassType get_type() const
{
static int dummy;
return reinterpret_cast<ClassType>(&dummy);
}
A static variable dummy will be created for each class you add this member function, so that the return value identifies uniquely the class.
I want to create a generic IEnumerable implementation, to make it easier to wrap some native C++ classes. When I try to create the implementation using a template parameter as the parameter to IEnumerable, I get an error.
Here's a simple version of what I came up with that demonstrates my problem:
ref class A {};
template<class B>
ref class Test : public System::Collections::Generic::IEnumerable<B^> // error C3225...
{};
void test()
{
Test<A> ^a = gcnew Test<A>();
}
On the indicated line, I get this error:
error C3225: generic type argument for 'T' cannot be 'B ^', it must be a value type or a handle to a reference type
If I use a different parent class, I don't see the problem:
template<class P>
ref class Parent {};
ref class A {};
template<class B>
ref class Test : public Parent<B^> // no problem here
{};
void test()
{
Test<A> ^a = gcnew Test<A>();
}
I can work around it by adding another template parameter to the implementation type:
ref class A {};
template<class B, class Enumerable>
ref class Test : public Enumerable
{};
void test()
{
using namespace System::Collections::Generic;
Test<A, IEnumerable<A^>> ^a = gcnew Test<A, IEnumerable<A^>>();
}
But this seems messy to me. Also, I'd just like to understand what's going on here - why doesn't the first way work?
In your first example, your inheritance line should read:
ref class Test : public System::Collections::Generic::IEnumerable<B>
(no reference marker on the template)
Then your usage line should read:
Test<A^> ^a = gcnew Test<A^>();
The reference markers go in the instantiation of the template, not the template itself.
Here's your sample, compilable:
using namespace System;
using namespace System::Collections::Generic;
ref class A {};
template<class B> ref class Test : public System::Collections::Generic::IEnumerable<B>
{
public:
B GetInstance()
{
return Activator::CreateInstance<B>();
}
virtual System::Collections::IEnumerator^ GetEnumeratorObj() =
System::Collections::IEnumerable::GetEnumerator
{
return nullptr;
}
virtual System::Collections::Generic::IEnumerator<B>^ GetEnumerator()
{
return nullptr;
}
};
void test()
{
Test<A^> ^a = gcnew Test<A^>();
}
Edit: Realized I should explain why this is. To the best of my understanding, the reason that you can't specify B^ in the IEnumerable inheritance is that IEnumerable is a generic with a constraint on it, while B is a template parameter which is unconstrained. Templates allow for much more flexible syntax, even when they govern ref objects, as they're still effectively "parsed text" even in C++/CLI. However, when they bump into generics with constraints, the rules get a lot tighter.