www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Tools for building a dynamic derived type? I need a push in the right

reply "Gary Willoughby" <dev nomad.so> writes:
I've been researching ways to accomplish creating a template that 
creates a special kind of derived type and i think i need a push 
in the right direction. Take this simple class:

class Person
{
	private string _name;
	private int _age;

	this(string name, int age)
	{
		this._name = name;
		this._age  = age;
	}

	public string getName()
	{
		return this._name;
	}

	public int getAge()
	{
		return this._age;
	}
}

I want to create a mock of this class which would mean achieving 
the following:

1). Extend the class
2). Override all public methods to do nothing (or look for 
enabled methods)
3). Provide a way of dynamically enabling methods with new return 
values

Extending the class is pretty easy and adding methods dynamically 
looks to be solved (TDPL 12.11.1) but it's the override all 
public methods to do something different which is beating me. I 
know it will probably involve mixins and dealing with tuples 
somewhere along the line but documentation is lacking everywhere 
i look.

std.traits gives me information about a type but using that 
information is where i need the documentation. e.g. i know the 
traits methods return tuples but how do you work with these 
tuples? how to Iterate through them? I seem to always get stuck 
when trying to iterate through tuples and generate compiler 
errors.

I've taken a look at the std.typecons source especially BlackHole 
and WhiteHole templates but i get lost. They are almost doing 
what i want but for abstract methods.

The general usage is probably going to be something like this:

class Mock(T) : T
{
     // Implementation
}

auto cat = Mock!Cat("Ginger"); // constructors supported.

auto person = Mock!Person();

person.addMethod("getName", delegate(){
     return "Foo";
});

person.addMethod("getAge", delegate(){
     return 10;
});

Any help will be greatly appreciated.
Aug 20 2013
next sibling parent reply "Kapps" <opantm2+spam gmail.com> writes:
On Tuesday, 20 August 2013 at 18:55:44 UTC, Gary Willoughby wrote:
 I've been researching ways to accomplish creating a template 
 that creates a special kind of derived type and i think i need 
 a push in the right direction. Take this simple class:

 class Person
 {
 	private string _name;
 	private int _age;

 	this(string name, int age)
 	{
 		this._name = name;
 		this._age  = age;
 	}

 	public string getName()
 	{
 		return this._name;
 	}

 	public int getAge()
 	{
 		return this._age;
 	}
 }

 I want to create a mock of this class which would mean 
 achieving the following:

 1). Extend the class
 2). Override all public methods to do nothing (or look for 
 enabled methods)
 3). Provide a way of dynamically enabling methods with new 
 return values

 Extending the class is pretty easy and adding methods 
 dynamically looks to be solved (TDPL 12.11.1) but it's the 
 override all public methods to do something different which is 
 beating me. I know it will probably involve mixins and dealing 
 with tuples somewhere along the line but documentation is 
 lacking everywhere i look.

 std.traits gives me information about a type but using that 
 information is where i need the documentation. e.g. i know the 
 traits methods return tuples but how do you work with these 
 tuples? how to Iterate through them? I seem to always get stuck 
 when trying to iterate through tuples and generate compiler 
 errors.

 I've taken a look at the std.typecons source especially 
 BlackHole and WhiteHole templates but i get lost. They are 
 almost doing what i want but for abstract methods.

 The general usage is probably going to be something like this:

 class Mock(T) : T
 {
     // Implementation
 }

 auto cat = Mock!Cat("Ginger"); // constructors supported.

 auto person = Mock!Person();

 person.addMethod("getName", delegate(){
     return "Foo";
 });

 person.addMethod("getAge", delegate(){
     return 10;
 });

 Any help will be greatly appreciated.
AutoImplement (http://dlang.org/phobos/std_typecons.html#.AutoImplement) from std.typecons should do what you want. Instead of implementing only abstract methods, you could make it implement all non-final methods by changing the 'what' template parameter to simply return true (final methods are skipped regardless). Then you could change the 'how' template parameter to return ReturnType!parent.init unless an argument is set in an AA. I can't say I've ever tried this though, so I'm not sure how well it would work in reality. https://github.com/QAston/DMocks-revived may interest you as well.
Aug 20 2013
parent "Gary Willoughby" <dev nomad.so> writes:
On Wednesday, 21 August 2013 at 03:37:46 UTC, Kapps wrote:
 On Tuesday, 20 August 2013 at 18:55:44 UTC, Gary Willoughby 
 wrote:
 I've been researching ways to accomplish creating a template 
 that creates a special kind of derived type and i think i need 
 a push in the right direction. Take this simple class:

 class Person
 {
 	private string _name;
 	private int _age;

 	this(string name, int age)
 	{
 		this._name = name;
 		this._age  = age;
 	}

 	public string getName()
 	{
 		return this._name;
 	}

 	public int getAge()
 	{
 		return this._age;
 	}
 }

 I want to create a mock of this class which would mean 
 achieving the following:

 1). Extend the class
 2). Override all public methods to do nothing (or look for 
 enabled methods)
 3). Provide a way of dynamically enabling methods with new 
 return values

 Extending the class is pretty easy and adding methods 
 dynamically looks to be solved (TDPL 12.11.1) but it's the 
 override all public methods to do something different which is 
 beating me. I know it will probably involve mixins and dealing 
 with tuples somewhere along the line but documentation is 
 lacking everywhere i look.

 std.traits gives me information about a type but using that 
 information is where i need the documentation. e.g. i know the 
 traits methods return tuples but how do you work with these 
 tuples? how to Iterate through them? I seem to always get 
 stuck when trying to iterate through tuples and generate 
 compiler errors.

 I've taken a look at the std.typecons source especially 
 BlackHole and WhiteHole templates but i get lost. They are 
 almost doing what i want but for abstract methods.

 The general usage is probably going to be something like this:

 class Mock(T) : T
 {
    // Implementation
 }

 auto cat = Mock!Cat("Ginger"); // constructors supported.

 auto person = Mock!Person();

 person.addMethod("getName", delegate(){
    return "Foo";
 });

 person.addMethod("getAge", delegate(){
    return 10;
 });

 Any help will be greatly appreciated.
AutoImplement (http://dlang.org/phobos/std_typecons.html#.AutoImplement) from std.typecons should do what you want. Instead of implementing only abstract methods, you could make it implement all non-final methods by changing the 'what' template parameter to simply return true (final methods are skipped regardless). Then you could change the 'how' template parameter to return ReturnType!parent.init unless an argument is set in an AA. I can't say I've ever tried this though, so I'm not sure how well it would work in reality. https://github.com/QAston/DMocks-revived may interest you as well.
Thanks that gave me a lot to work with! :)
Sep 07 2013
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2013-08-20 20:55, Gary Willoughby wrote:

 The general usage is probably going to be something like this:

 class Mock(T) : T
 {
      // Implementation
 }

 auto cat = Mock!Cat("Ginger"); // constructors supported.

 auto person = Mock!Person();

 person.addMethod("getName", delegate(){
      return "Foo";
 });

 person.addMethod("getAge", delegate(){
      return 10;
 });

 Any help will be greatly appreciated.
I'm not exactly sure how you want it to work, but this is an idea: Create and store an instance of T in Mock. Implement opDispatch in Mock and forward an methods added by addMethod to the delegate. If no delegate exists for that method forward to the instance of T instead. http://dlang.org/operatoroverloading.html#Dispatch -- /Jacob Carlborg
Aug 20 2013