It's time to re-discuss partial class

There are several discussions about partial classes, but they are old and inactive.

So I want to re-discuss partial class again.

TL;DR

Q. Why It’s time now?
A. The KSP is released, so it’s easy to write code generator for Kotlin.
Partial class is for code generator, so it’s time now.

Q. What’s the partial class in this discussion
A. Something like partial class in C# 2.0 with partial member in C# 9.0.

Q. Goals?
A. See #goals

Q. Use cases?
A. Code generators

Why It’s time now?

The Kotlin Symbol Processor, a code generating system like Annotation Processor but for Kotlin
by Google, talked in
Official Blog and
Official documentation, have been released
last month.

With this system, we can easily write compile time source generators for Kotlin.
So, I think it’s time to add future for code generation.

What’s the partial class in this discussion

First, I want to make clear which partial classes/members I want to discuss.
I want to refer partial classes/members in C# but C# have multiple partial classes/members.

  1. partial classes since C# 2.0

    Declare class in separated files.

  2. partial methods since C# 3.0

    Separate declaring method and defining event handling method in separated files.
    In this feature, definition can be omitted and calling expression will be removed if not defined.
    This feature is intended to write declaration and call in generated code and
    write definition (including body) in handwritten code.

  3. partial method since C# 9.0

    Separate declaring method and defining method in separated files.
    This feature is intended to write declaration in handwritten code and
    write definition in generated code (based on of declaration).

I want to discuss 1 and 3, partial class in C# 2.0 and methods since C# 9.0.
Because I think something like partial methods in 3.0 can be implemented as an extension of partial method in 9.0.

One example of the extension in the feature like partial method in C# 3.0

For partial methods with return type that is a object and annotated with @OptionalImplementation
that doesn’t have definition, generate empty method that returns the object.

Goals

  • Provide the way to write class in multiple places.
  • Provide the way to separate declaration and definition/implementation.

Use cases

The main use cases of this feature is combining generated code and
handwritten code in a class.

One example is equals and hashCode generator.

With following handwritten class, the generator want to
generate equals and hashCode as following second code.

@GeenrateEquals(props = [
    "property1",
    "property2",
])
partial class SomeClass(
    val property1: String,
    val property2: String,
)
// generated code
partial class SomeClass {
    override fun equals(that: Any?) = that != null
                && that::class == this::class
                && this.property1 == (that as SomeClass).property1
                && this.property2 == that.property2
    override fun hashCode() =
        this.property1.hashCode().times(31)
            .plus(this.property2.hashCode())
}
3 Likes