www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Help about Template and class inheritance

reply Heromyth <bitworld qq.com> writes:
Here is a sample code

```d
import std.stdio;

class Future(T)
{
	T result;

	this(T r) {
		this.result = r;
	}
}

interface IExecutorService {
	// Future!(T) submit(T)(T result);  // can't be implemented
}

abstract class ExecutorService : IExecutorService {
	 Future!(T) submit(T)(T result) {
		return new Future!(T)(result);
	}
}

class ThreadPoolExecutor : ExecutorService {
	// alias submit = ExecutorService.submit;
	
	// override Future!(T) submit(T)(T result) { // can't override it
	// 	return new Future!(T)(result + 10);
	// }
}

void main()
{
	ThreadPoolExecutor service = new ThreadPoolExecutor();
	ExecutorService serviceBase = service;
	IExecutorService serviceInterface = service;

	Future!(int) f = service.submit!int(12);
	writeln(f.result);
	
	f = serviceBase.submit!int(12);
	writeln(f.result);

	// f = serviceInterface.submit!int(12);
	// writeln(f.result);
}

```

The **submit** can't be defined in D as done in Java. See also 
(search for exchangeMessageVectorsAsync):

https://www.programcreek.com/java-api-examples/?code=aarmea/noise/noise-master/app/src/main/java/com/alternativeinfrastructures/noise/sync/StreamSync.java

So, is there a better way to do this in D?
Any suggestions are welcome.
Thanks.
Oct 14 2018
parent reply Basile B. <b2.temp gmx.com> writes:
On Sunday, 14 October 2018 at 13:21:00 UTC, Heromyth wrote:
 Here is a sample code

 ```d
 import std.stdio;

 class Future(T)
 {
 	T result;

 	this(T r) {
 		this.result = r;
 	}
 }

 interface IExecutorService {
 	// Future!(T) submit(T)(T result);  // can't be implemented
 }

 abstract class ExecutorService : IExecutorService {
 	 Future!(T) submit(T)(T result) {
 		return new Future!(T)(result);
 	}
 }

 class ThreadPoolExecutor : ExecutorService {
 	// alias submit = ExecutorService.submit;
 	
 	// override Future!(T) submit(T)(T result) { // can't override 
 it
 	// 	return new Future!(T)(result + 10);
 	// }
 }

 void main()
 {
 	ThreadPoolExecutor service = new ThreadPoolExecutor();
 	ExecutorService serviceBase = service;
 	IExecutorService serviceInterface = service;

 	Future!(int) f = service.submit!int(12);
 	writeln(f.result);
 	
 	f = serviceBase.submit!int(12);
 	writeln(f.result);

 	// f = serviceInterface.submit!int(12);
 	// writeln(f.result);
 }

 ```

 The **submit** can't be defined in D as done in Java. See also 
 (search for exchangeMessageVectorsAsync):

 https://www.programcreek.com/java-api-examples/?code=aarmea/noise/noise-master/app/src/main/java/com/alternativeinfrastructures/noise/sync/StreamSync.java

 So, is there a better way to do this in D?
 Any suggestions are welcome.
 Thanks.
The basic problem you're faced to here is that D class / interface member functions that are templatized are never virtual. I'm not sure if i understand well the JAVA pattern you try to reproduce but since D interfaces can be templatized you can do something like this, using variadics: import std.stdio; class Future(T) { T result; this(T r) { this.result = r; } } interface IExecutorService(Ts...) { static foreach(T; Ts) Future!T submit(T result); } abstract class ExecutorService(Ts...) : IExecutorService!Ts { static foreach(T; Ts) Future!T submit(T result) { return new Future!(T)(result); } } class ThreadPoolExecutor : ExecutorService!int { override Future!int submit(int result) { return new Future!int(result + 10); } } void main() { ThreadPoolExecutor service = new ThreadPoolExecutor(); ExecutorService!int serviceBase = service; IExecutorService!int serviceInterface = service; Future!(int) f = service.submit(12); writeln(f.result); f = serviceBase.submit(12); writeln(f.result); f = serviceInterface.submit(12); writeln(f.result); } so that you can submit and have Future for several types.
Oct 14 2018
parent Heromyth <bitworld qq.com> writes:
On Sunday, 14 October 2018 at 15:06:49 UTC, Basile B. wrote:
 The basic problem you're faced to here is that D class / 
 interface member functions that are templatized are never 
 virtual. I'm not sure if i understand well the JAVA pattern you 
 try to reproduce but since D interfaces can be templatized you 
 can do something like this, using variadics:
That's a good try. I want to have a try with template mixin. About Java's pattern, see also: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html The interface ExecutorService has many implements like AbstractExecutorService, ForkJoinPool, ScheduledThreadPoolExecutor, ThreadPoolExecutor etc. The sample above is updated: import std.stdio; class Future(T) { T result; this(T r) { this.result = r; } } interface IExecutorService { // Future!(T) submit(T)(T result); // can't be implemented } abstract class ExecutorService : IExecutorService { Future!(T) submit(T)(T result) { return new Future!(T)(result); } } class ThreadPoolExecutor : ExecutorService { // alias submit = ExecutorService.submit; // override Future!(T) submit(T)(T result) { // can't override it // return new Future!(T)(result + 10); // } } class ForkJoinPool : ExecutorService { // alias submit = ExecutorService.submit; // override Future!(T) submit(T)(T result) { // can't override it // return new Future!(T)(result * 10); // } } void testBase(ExecutorService service) { writeln("testBase: ", typeid(service)); Future!(int) f = service.submit!int(12); writeln(f.result); } void testInterface(IExecutorService service) { writeln("testInterface: ", typeid(service)); writeln("testInterface: ", typeid(cast(Object)service)); // Future!(int) f = service.submit!int(12); // writeln(f.result); } void main() { ThreadPoolExecutor threadPool = new ThreadPoolExecutor(); ForkJoinPool forkJoinPool = new ForkJoinPool(); testBase(threadPool); writeln(); testBase(forkJoinPool); writeln("\n"); testInterface(threadPool); writeln(); testInterface(forkJoinPool); }
Oct 14 2018