Scala: Наследование против функции высшего порядка - PullRequest
0 голосов
/ 01 марта 2019

Скажем,

class ClientFunc {
  def client(s: String): Future[Service] = ....

  def m1(s: String) = {
    client(s).map( ...... )
  } 
  ...//there are multiple such methods like m1 in this class which 
depends on "def client".       
}

Теперь нам нужно добавить еще одного клиента того же типа, с другой реализацией, и мы хотим использовать его вместе с существующим, основываясь на требованиях.

Таким образом, есть два способа решения этой проблемы.Решение первое: использование наследования, например, сделать метод клиента абстрактным в родительском и предоставить дочерние классы и clientB для реализаций, для двух разных клиентов.

class clientA extends ClientFunc {
   def client(s: String): Future[Service] = ....
}  
class clientB extends ClientFunc {
   def client(s: String): Future[Service] = ....
} 

Использование как обычно,

 clientAInstance.m1("str")
 and
 clientBInstance.m1("str")

Какдля каждого случая использования я должен использовать clientA и clientB одновременно, поэтому мне нужно внедрить обоих клиентов в сервис.

Другое решение: сделать "def m1" как функции более высокого порядка и передать в него клиента, сохранить класс ClientFunc как есть, добавить еще одну функцию для другого клиента, например (def clientB),

class ClientFunc {
  def clientA(s: String): Future[Service] = ....
  def clientB(s: String): Future[Service] = ....

  def m1(s: String, cl:String => Future[Service]) = {
   cl(s).map( ...... )
  } 

}

Теперь, когда мне нужно позвонить, я просто позвоню, как,

 ClientFuncInstance.m1("str", ClientFuncInstance.clientA)
 and
 ClientFuncInstance.m1("str", ClientFuncInstance.clientB)

нет необходимости вводить ClientFunc два раза.

Вопрос в том, какой из них предпочтительнее в Scala/ функциональное программирование?& Зачем?если есть какой-нибудь другой способ, пожалуйста, предложите

1 Ответ

0 голосов
/ 01 марта 2019

На мой взгляд, лучший способ - добавить client в конструктор:

class ClientFunc(client: String => Future[Service]) {
  def m1(s: String) = {
    client(s).map( ...... )
  } 
  ...
}

Вы можете добавлять новые реализации (включая макеты для тестирования) без необходимости изменять существующий код.


[Обновить после комментариев]

Вы бы использовали его так:

def clientA(s: String): Future[Service] = ....
def clientB(s: String): Future[Service] = ....

val clientFuncA = new ClientFunc(clientA)
val clientFuncB = new ClientFunc(clientB)

class Service(funcA: ClientFunc, funcB: ClientFunc) {
  def flag = ...
  def client = if (flag) { funcA } else { funcB }

  def m1(s: String) = {
    client.m1(s)
  }
}

val service = new Service(clientFuncA, clientFuncB)
...