В чем преимущество наличия частного конструктора и использования метода внутри объекта-компаньона для создания экземпляра класса? - PullRequest
0 голосов
/ 13 февраля 2019

Я столкнулся с этим кодом, и я не уверен, зачем кому-то это делать.По сути, автор решил сделать конструктор класса частным, чтобы его нельзя было создать вне файла, и добавил открытый метод к объекту-компаньону в классе, который создает новый экземпляр этого класса.В чем выгода этого подхода?

Вот что я нашел:

class Foo private constructor(private val arg1: Any) {
    //more code here..
    companion object {
        fun newFoo(arg1: Any) = Foo(arg1 = arg1)
    }
}

Почему это лучше, чем этот?

class Foo(private val arg1: Any) {
    //more code here..
}

Ответы [ 4 ]

0 голосов
/ 14 февраля 2019

Существует несколько преимуществ предоставления фабричного метода вместо общедоступного конструктора, в том числе:

  • Он может выполнить большую обработку перед вызовом construstor.(Это может быть важно, если конструктор суперкласса принимает параметры, которые необходимо вычислить.)

  • Он может возвращать кэшированные значения вместо новых экземпляров, где это необходимо.

  • Может возвращать подкласс.(Это позволяет сделать верхний класс интерфейсом, как отмечено в другом ответе.) Точный класс может отличаться для разных вызовов и даже может быть анонимным типом.

  • Может иметьимя (как отмечено в другом ответе).Это особенно важно, если вам нужно несколько методов с одинаковыми параметрами.(Например, объект Point, который может быть построен из прямоугольных или полярных координат.) Однако фабричному методу не нужно конкретное имя;если вы реализуете метод invoke() в сопутствующем объекте, вы можете вызывать его точно так же, как конструктор.

  • Это облегчает изменение реализации класса безвлияет на его открытый интерфейс.

Он также имеет важный недостаток:

  • Он не может использоваться конструкторами подклассов.

Кажется, что фабричные методы используются в Kotlin меньше, чем Java, возможно, из-за более простого синтаксиса Kotlin для основных конструкторов и свойств.Но они все еще заслуживают рассмотрения, особенно учитывая, что сопутствующие объекты Kotlin могут наследовать.

Более подробную информацию см. В этой статье , в которой дана рекомендация в EffectiveJava и как это относится к Kotlin.

0 голосов
/ 14 февраля 2019

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

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

0 голосов
/ 14 февраля 2019

Есть много полезных случаев, например, что описал Кискае.Другим хорошим вариантом будет возможность «давать имена вашим конструкторам»:

class Foo<S: Any, T: Any> private constructor(private val a: S, private val b: T) {
    //more code here...
    companion object {
        fun <S: Any> createForPurposeX(a: S) = Foo(a = a, b = "Default value")
        fun createForPurposeY() = Foo(a = 1, b = 2)
    }
}

Call site:

Foo.createForPurposeX("Hey")
Foo.createForPurposeY()

Примечание: вы должны использовать универсальные типы вместо Any.

0 голосов
/ 13 февраля 2019

Если вы хотите изменить Foo на интерфейс в будущем, код, основанный на методе, продолжит работать, поскольку вы можете вернуть конкретный класс, который все еще реализует Foo, в отличие от конструктора, который больше не существует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...