-
Notifications
You must be signed in to change notification settings - Fork 14
Class header formatting #2
Comments
Personally, I use a different style: class C(
val a: String,
val b: String
) : SuperType {
val d: String = ""
} This has the benefit that all properties are horizontally aligned. |
Also formatting suggested by @cypressious is more consistent in terms of In addition to what was already mentioned before I think the following examples of formatting should be covered:
|
Same if the list of super types is long:
|
@voddan Do not like curly bracket on the new line |
@gildor same reason why |
@voddan I prefer style from @cypressious comment. |
@gildor could you please provide an example of a formatting for a class with an empty constructor but with a long list of super types? |
Also, I'm not sure about a position of a colon. I think for a colon we should use the same rule as for expression body formatting #1 Because if we move a colon to the next line Idea formats it with this way:
|
The formatter can be improved if it is decided that this style looks better. |
Your first example has a flaw that the first line of the class body mixes with the last line of the declaration:
A solution to that is to add a new line before the |
@voddan Agree, that it's not perfect, but more compact and consistent with other blocks formating (opening curly bracket on the same line)
or with a colon on the next lline (I do not have strong opinion about colon position) :
|
@gildor the problem I mentioned is very common and a huge PITA. If you dislike the rule I proposed (it looks meh, but I don't know a better solution) you should actively express it toward the rule at the header of this topic, since I believe the are at sync |
Small addition for constructor annotations: class Foo @Inject constructor(
val prop: String
) {
} |
Trying to make some crazy class-headers just to see how I can keep it readable when a ton of logic is in the header. I ended up fairly happy with something like: open class FooActivity
@Inject
@JvmOverloads
protected constructor(
val foo1: String,
val foo2: Map<String, Map<Int, String>>,
val foo3: SomeInterface1? = null
) : Activity(),
SomeInterface1 by foo3 ?: object: SomeInterface1 {},
SomeInterface2 {
// Just foo1 with its length added on at the end
val foo4 = "${foo1}:${foo1.length}"
init {
if (foo1.length > 10) {
throw IllegalArgumentException("Can't set foo1 to more than 10 char long")
}
}
fun foo() {}
fun getFoo1Length() = foo1.length
fun someComplicatedThing() {
// TODO: Make this do a cool thing
TODO()
}
} |
I wouldn't put the parantheses of the constructor on separate lines. 2016-06-14 20:55 GMT+02:00 Ruckus T-Boom [email protected]:
|
@cypressious I was being facetious and removed my comment as it wasn't helpful. Please do not take it seriously. I would never actually write code like that. |
I generally like @kevinmost proposal but I prefer a more compact style that uses more horizontal space (I generally set my editor margin out to 130 chars, which is easily viewable in one screen on modern monitors). The constructor annotations are part of the constructor which is part of the class declaration so I like keeping those together. I also don't like multiple indentation -- I like things to be visually aligned so I keep everything to two: open class FooActivity @Inject @JvmOverloads protected constructor(
val foo1: String,
val foo2: Map<String, Map<Int, String>>,
val foo3: SomeInterface1? = null
) : Activity(),
SomeInterface1 by foo3 ?: object: SomeInterface1 {},
SomeInterface2 {
// Just foo1 with its length added on at the end
val foo4 = "${foo1}:${foo1.length}"
init {
if (foo1.length > 10) {
throw IllegalArgumentException("Can't set foo1 to more than 10 char long")
}
}
fun foo() {}
fun getFoo1Length() = foo1.length
fun someComplicatedThing() {
// TODO: Make this do a cool thing
TODO()
}
} |
@rocketraman 130 characters is pretty wide, and likely to cause you problems if you want to use a command line editor no? Along those lines, in my experience names get very long, and if you consider access restriction and annotations on the constructor, we get this: open class CommandAndServiceAndParkadeControllerViewService @Inject @JvmOverloads protected constructor(
val foo1: String,
val foo2: Map<String, Map<Int, String>>,
val foo3: SomeInterface1? = null
) : Activity(),
SomeInterface2 { which means I think its more conventional to simply do what the jquery text box on github is already doing for me: put a newline between your first annotation and the end of the class name open class CommandAndServiceAndParkadeControllerViewService
@Inject @JvmOverloads protected constructor(
val foo1: String,
val foo2: Map<String, Map<Int, String>>,
val foo3: SomeInterface1? = null
) : Activity(),
SomeInterface2 { note I removed your anonymous delegating class, that seems like it would be enormously obnoxious to implement, and I'm still warming up to the idea of inheritance by delegation. The formatting there would be really difficult: class FooActivity (
val foo1: String
) : Activity(),
SomeInterface1 by foo3 ?: object: SomeInterface1 {
override fun things(): Unit{
//code
}
}, I think in general you're better off delegating the whole thing to a local method if thats legal kotlin: class FooActivity (
val foo1: String
) : Activity(),
SomeInterface1 by asSomeInterface1(foo3){
//...
fun asSomeInterface1(arg: Foo3): SomeInterface1{
return foo3 ?: //...
}
} |
Hmm, I've never had an issue with it and I use the command line all the time. Though rarely to edit code. Occasionally github does not show the entire line on the web. I've never found it a problem. Even with the name you gave (which honestly, I'd think about renaming to be shorter :-) ), the declaration goes out to 104 chars. No biggie. |
The following feels somewhat wrong.
There're 1204 sad faces and long sad faces in Kotlin sources. |
I'm trying to put it all together. So for short header: class Person(id: Int, name: String) {
//...
} for multiple arguments: class Person(
id: Int,
name: String,
surname: String
) {
//...
} class Person(
id: Int,
name: String,
surname: String
): Human() {
//...
} Multiple with multiple arguments on extension: class Person(
id: Int,
name: String,
surname: String
): Human<Person>(id, name) {
//...
} Multiple with multiple arguments on extension and interfaces: class Person(
id: Int,
name: String,
surname: String
): Human<Person>(id, name),
NotADog,
Somebody {
//...
} Is it correct? |
Is there a way to have 4-space indent for the class arguments? Because with the default 8 spaces it looks not so pretty: class Person(
id: Int,
name: String,
surname: String
): Human<Person>(id, name),
NotADog,
Somebody {
//...
} |
@Jeevuz The indent for primary constructor arguments is controlled by the "Continuation Indent" setting in the code style settings for Kotlin. I have that set to the same as the normal indent, but I too would like a separate control for that indent specifically. |
In the current style guide when the 4-space indentation gets combined with the "opening brace always on the same line" and "every interface on its own line in class header" it ends up looking like this (copied from https://github.com/JetBrains/kotlin-web-site/blob/yole/styleguide/pages/docs/reference/coding-conventions.md):
while an extra empty line does add some separation from class header to its body it is still somewhat confusing to see class header continued into the body on the same indent level. I, personally, would really have preferred an opening brace on a separate line just for the case of multi-line interface list (but in no other case):
Thumbs up or down? |
I agree that it's a little awkward to have the body and the class header left-aligned, but I don't think that it's worth making an exception for the opening brace on a separate line in this case. When you have actual syntax highlighting, it's really not much of a problem... any members of the body will be highlighted differently: class Person(
id: Int,
name: String,
surname: String
) : Human(id, name),
KotlinMaker {
fun memberFunction() {
// ...
}
} The real problem is probably that primary constructor parameters coincidentally align with the supertypes. |
So what about the I think moving it on the new line is better because it looks more consistent with the chosen header style and also looks like the class MyFavouriteVeryLongClassHolder
: MyLongHolder<MyFavouriteVeryLongClass>(),
SomeOtherInterface,
AndAnotherOne {
fun foo() {}
} |
Hi all! class Something(
val param: Param,
foo: Foo,
bar: Bar,
andMore: More,
andOneThatCrossesTheLine
) : SomethingSupertype(
foo,
bar,
andMore,
andOneThatCrossesTheLine
), Interface1, // this line loocks ugly
Interface2 {
fun funnyFun() {
...
}
} |
Well, I'd first try finding a solution that doesn't need this much inheritance... But if needed, I'd probably format it something like this:
|
Thanks, I like your solution. |
If the class header (primary constructor and superclass list) doesn't fit on a single line, put the opening curly brace of the class on a separate line, with no indentation.
The text was updated successfully, but these errors were encountered: