Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

419
Visualizações
How to create an inner class where only the outer class can access the constructor, but the rest is visible everywhere?

I originally wanted to create a class that can abort instantiation in constructor, but according to this link I should instead use a Factory class. But now I want to prevent anyone except the factory class from creating an object of class "Inner" while giving access to the methods of the inner class to everyone.

I have already tried this answer.

import java.util.Date

object InnerFactory {

    class Inner private constructor(startDate: Date? = null, endDate: Date? = null) {
        fun getTimeDifference(): Long? {
            //calculates time difference but doesn't matter to this example
        }
    }

    fun createInnerObject(startDate: Date? = null, endDate: Date? = null): Inner? {
        if (startDate != null && endDate != null && !endDate.after(startDate)) {
            return null
        }

        return Inner(startDate, endDate)
    }

}

I would use it like the following:

val date1 = Date(1547600000)
val date2 = Date(1547600600)
val inner = InnerFactory.createInnerObject(date1, date2) //should return an instance
val invalidInner = InnerFactory.createInnerObject(date2, date1) //should not return an instance because the "endDate" is before "startDate"
val difference = inner?.getTimeDifference()

It says "cannot access '<init>': it is private in 'Inner'" when hovering over my usage of the constructor in the "createInnerObject" function.

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

What you could do:

  • introduce an interface Inner with all the necessary functions that should be exposed
  • make all the class(es) private and implement that interface

Sample:

object InnerFactory {

  interface Inner {
    fun getTimeDifference(): Long?
  }

  private class InnerImpl(startDate: Date? = null, endDate: Date? = null) : Inner {
    override fun getTimeDifference(): Long? = TODO("some implementation")
  }


  fun createInnerObject(startDate: Date? = null, endDate: Date? = null): Inner? {
    if (startDate != null && endDate != null && !endDate.after(startDate)) {
      return null
    }
    return InnerImpl(startDate, endDate) // InnerImpl accessible from here but not from outside of InnerFactory...
  }
}

Now you can't access InnerImpl from outside anymore, but still have all the necessary functions available:

// the following all work as it deals with the interface
val inner = InnerFactory.createInnerObject(date1, date2) //should return an instance
val invalidInner = InnerFactory.createInnerObject(date2, date1) //should not return an instance because the "endDate" is before "startDate"
val difference = inner?.getTimeDifference()

// the following will not compile:
InnerImpl()
over 4 years ago · Santiago Trujillo Relatório

0

Unfortunately, private members of Kotlin inner classes are not accessible from the outer instance:

private means visible inside this class only
Kotlin reference / Visibility modifiers

However, Java is not this restrictive with its visibility modifiers:

access is permitted if and only if it occurs within the body of the top level type (§7.6) that encloses the declaration of the member or constructor.
Java Language Specification / §6 Names / §6.6 Access Control / §6.6.1 Determining Accessibility

This is one of the only (annoying) cases I have found where Kotlin's rules make a common Java pattern impossible.

The only workarounds (if you want to keep your current structure) would be to rewrite this class in Java, or to expose this constructor with a less restrictive visibility (e.g. internal.)

There was a discussion about this on the Kotlin forums - it seems that this is a JVM limitation, and that it only works in Java because the compiler generates appropriate synthetic accessors.

over 4 years ago · Santiago Trujillo Relatório

0

You could make make the constructor protected. This way you only expose it to subclasses, in this case PrivateClass. Then you will create an instance of PrivateClass or null but return it as InnerClass?.

object InnerFactory {

    fun createInnerObject(startDate: Date? = null, endDate: Date? = null): Inner? {
        // return null here if conditions are not met
        return PrivateClass(startDate, endDate)
    }

    open class Inner protected constructor(val startDate: Date?, val endDate: Date?) {
        fun getTimeDifference(): Long? { /* ... */ }
    }

    private class PrivateClass(startDate: Date?, endDate: Date?): Inner(startDate, endDate)
}
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda