У меня два докладчика: FirstPresenter и SecondPresenter. FirstPresenter соответствует протоколу PresenterProtocol. SecondPresenter необходимо использовать все функции из FirstPresenter, но с двумя дополнительными.

protocol PresenterProtocol: class {
  func one()
  func two()
  func third()
}

class FirstPresenter: PresenterProtocol {

  func one() {

  // do something
 }

  func two() {

  // do something
 }

  func third() {

  // do something
 }
}

И затем у меня есть SecondPresenter, и мне нужно использовать ту же реализацию, что и FirstPresenter (но я хочу избежать наследования, я хочу сделать это с протоколами)

class SecondPresenter: PresenterProtocols {

var firstPresenter: PresenterProtocol = FirstPresenter()

 func one() {
    firstPresenter.one()
  // do something
 }

  func two() {
    firstPresenter.two()
  // do something
 }

  func third() {
    firstPresenter.third()
  // do something
 }

 func additionalFunction() {
   // do something more
 }
}

Я не уверен, что вызов функции firstpresenter - хороший способ решить эту проблему, потому что это просто переписывание. Интересно также использовать реализацию по умолчанию. Как лучше всего делиться функциями?

1
jackbob 17 Сен 2021 в 19:59

2 ответа

Лучший ответ

Ваш код на самом деле не зависит от методов, которые вы определяете, поэтому они не должны быть требованиями. Это расширения. Как написано, ваш код будет:

// This is where *requirements* go. Not shared code.
protocol PresenterProtocol: class {}

// This is your shared code
extension PresenterProtocol {
  func one() {

  // do something
 }

  func two() {

  // do something
 }

  func third() {

  // do something
 }
}

// And FirstPresenter needs nothing else
class FirstPresenter: PresenterProtocol {}

// SecondPresenter gets those, and also has other things
class SecondPresenter: PresenterProtocols {
 func additionalFunction() {
   // do something more
 }
}

Держу пари, что у one() действительно есть некоторые требования. Ему нужны разработчики, чтобы что-то предоставить . Это то, что входит в ваш PresenterProtocol. Например:

extension PresenterProtocol {
  func one() {
      doFirstThing()   // Something the implementer must do
      doSecondThing()  // Something the implementer must do
  }
}

В этом случае вы должны добавить их в качестве требований:

protocol PresenterProtocol {
    func doFirstThing()
    func doSecondThing()
}

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

1
Rob Napier 17 Сен 2021 в 17:31

Насколько я понимаю, наличие родительского класса - лучшая реализация. Но, если вы не хотите, у swift protocols есть изящный трюк: протоколы можно расширять.

Позвольте мне продемонстрировать использование вашего кода,

protocol PresenterProtocol: class {
  func one()
  func two()
  func third()
}

// Adding the extenstion/default implementation
extension PresenterProtocol {
  func one() {
    print("one was pressed")
  }

  func two() {
    print("two was pressed")
  }

  func third() {
    print("third was pressed")
  }
}

Таким образом, любой класс, соответствующий PresenterProtocol, будет использовать так называемую «реализацию по умолчанию» (что является другим способом обозначить расширения протокола), если вы не переопределите метод в классе.

Таким образом, ваше использование будет выглядеть примерно так, как показано ниже, где вам не нужно заново реализовывать 3 метода.

class SecondPresenter: PresenterProtocol {
  // Calling default implementations
  func someFunction() {
    one() 
    two()
    third()
  }
}
.
.
.
class FirstPresenter: PresenterProtocol {
  func someFunction() {
    one()
    two()
    third()
  }
}

Если вам нужна дополнительная помощь в обучении, я настоятельно рекомендую прочитать HackingWithSwift Учебник

0
Visal Rajapakse 17 Сен 2021 в 17:26