Re: class Object with Dependency Injection

2023-06-18 Thread Salih Dincer via Digitalmars-d-learn

On Sunday, 18 June 2023 at 16:58:15 UTC, Ali Çehreli wrote:
The problem is with the deduced type of 'services'. I don't 
know the mechanism behind it but the common type of 'truck' and 
'ship' are deduced to be Object. Apparently, their interfaces 
don't take part in that decision. I don't know why.


This is very interesting because it looks like a bug.  Why is 
there no problem in an abstracted object, but things get confused 
in the interface (ITransport)?


On Sunday, 18 June 2023 at 16:58:15 UTC, Ali Çehreli wrote:
One solution is to help the compiler by casting them to your 
desired interface:


In fact, there is no need to cast:

```d
interface ITransport
{
  string deliver();
}

//...

void main()
{
  auto truck = new Truck;
  ITransport ship = new Ship;

/* or
  ITransport truck = new Truck;
  auto ship = new Ship;

// or

  ITransport truck = new Truck;
  ITransport ship = new Ship;//*/
}
```

SDB@78


Re: class Object with Dependency Injection

2023-06-18 Thread Ali Çehreli via Digitalmars-d-learn

On 6/18/23 07:37, Salih Dincer wrote:

>auto truck = new Truck;
>auto ship = new Ship;
>
>auto services = [ truck, ship ];

The problem is with the deduced type of 'services'. I don't know the 
mechanism behind it but the common type of 'truck' and 'ship' are 
deduced to be Object. Apparently, their interfaces don't take part in 
that decision. I don't know why.


One solution is to help the compiler by casting them to your desired 
interface:


  auto services = [ cast(ITransport)truck, cast(ITransport)ship ];

Or you can put the casts inside a function that could hide the 
complexity below:


  import std.algorithm;
  import std.range;
  auto services = [ truck, ship ].map!(s => cast(ITransport)s).array;

Ali



class Object with Dependency Injection

2023-06-18 Thread Salih Dincer via Digitalmars-d-learn
Hi, below is an example of DI-dependency injection with 3 
versions nested in the code. If you remove the leading // 
characters, you will not get the "no property `deliver` for 
`service` of type `object.Object`" error.  Because version-2I 
with interface wants its methods to depend on Object..


```d
//abstract class /* toggle-code
interface //* ^---version 2A */
ITransport
{
  string deliver();
}

class Ship : ITransport
{
  override string deliver()
  {
return "Ship Deliver";
  }
}

class Truck : ITransport
{
  override string deliver()
  {
return "Truck Deliver";
  }
}

abstract class Logistics
{
  ITransport createTransport();

  auto operations()
  {
return createTransport.deliver();
  }
}

class RoadLogistics : Logistics
{
  override ITransport createTransport()
  {
return new Truck();
  }
}

class SeaLogistics : Logistics
{
  override ITransport createTransport()
  {
return new Ship();
  }
}

import std.stdio;
void main()
{
  // DI version 1:
  auto sl = new SeaLogistics;
  auto rl = new RoadLogistics;

  auto logistics = [ sl, rl ];
  foreach(deliver; logistics)
  {
auto str = deliver.operations();
str.length.writeln(": ", str);
  }

  import std.range : repeat;
  "÷ ".repeat(9).writefln!"%-(%s%)";

  // A->I version 2:
  auto truck = new Truck;
  auto ship = new Ship;

  auto services = [ truck, ship ];
  foreach(service; services)
  {
auto str = service.deliver();
str.length.writeln(": ", str);
  }
}
```
Maybe using an abstract class instead of interface or not using 
auto will solve the problem, but I can't accept the situation!  I 
wonder what makes the interface special?


SDB@79