Skip to content

Commit f3e6c15

Browse files
committed
Revert "Apply suggestions from code review"
This reverts commit 4f548e9.
1 parent 4f548e9 commit f3e6c15

File tree

1 file changed

+9
-56
lines changed

1 file changed

+9
-56
lines changed

_overviews/tutorials/binary-compatibility-for-library-authors.md

Lines changed: 9 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -185,27 +185,10 @@ To achieve that, follow this pattern:
185185

186186
Example:
187187

188-
{% tabs case_class_compat_1 class=tabs-scala-version %}
188+
{% tabs case_class_compat_1 %}
189+
{% tab 'Scala 3 Only' %}
189190

190-
{% tab 'Scala 2' %}
191-
~~~ scala
192-
// Mark the primary constructor as private
193-
case class Person private (name: String, age: Int) {
194-
// Create withXxx methods for every field, implemented by using the copy method
195-
def withName(name: String): Person = copy(name = name)
196-
def withAge(age: Int): Person = copy(age = age)
197-
}
198-
object Person {
199-
// Create a public constructor (which uses the primary constructor)
200-
def apply(name: String, age: Int) = new Person(name, age)
201-
// Make the extractor private
202-
private def unapply(p: Person): Some[Person] = Some(p)
203-
}
204-
~~~
205-
{% endtab %}
206-
207-
{% tab 'Scala 3' %}
208-
~~~ scala
191+
```scala
209192
// Mark the primary constructor as private
210193
case class Person private (name: String, age: Int):
211194
// Create withXxx methods for every field, implemented by using the copy method
@@ -215,64 +198,38 @@ object Person:
215198
// Create a public constructor (which uses the primary constructor)
216199
def apply(name: String, age: Int) = new Person(name, age)
217200
// Make the extractor private
218-
private def unapply(p: Person): Person = p
219-
~~~
201+
private def unapply(p: Person) = p
202+
```
220203
{% endtab %}
221-
222204
{% endtabs %}
223205
This class can be published in a library and used as follows:
224206

225-
{% tabs case_class_compat_1_b %}
226-
{% tab 'Scala 2 and 3' %}
227207
~~~ scala
228208
// Create a new instance
229209
val alice = Person("Alice", 42)
230210
// Transform an instance
231211
println(alice.withAge(alice.age + 1)) // Person(Alice, 43)
232212
~~~
233-
{% endtab %}
234-
{% endtabs %}
235213

236214
If you try to use `Person` as an extractor in a match expression, it will fail with a message like “method unapply cannot be accessed as a member of Person.type”. Instead, you can use it as a typed pattern:
237215

238-
{% tabs case_class_compat_1_c class=tabs-scala-version %}
239-
{% tab 'Scala 2' %}
240-
~~~ scala
241-
alice match {
242-
case person: Person => person.name
243-
}
244-
~~~
245-
{% endtab %}
246-
{% tab 'Scala 3' %}
247216
~~~ scala
248217
alice match
249218
case person: Person => person.name
250219
~~~
251-
{% endtab %}
252-
{% endtabs %}
253220
Later in time, you can amend the original case class definition to, say, add an optional `address` field. You
254221
* add a new field `address` and a custom `withAddress` method,
255222
* add the former constructor signature as a secondary constructor, private to the companion object. This step is necessary because the compilers currently emit the private constructors as public constructors in the bytecode (see [#12711](https://github.com/scala/bug/issues/12711) and [#16651](https://github.com/lampepfl/dotty/issues/16651)).
256223

257-
{% tabs case_class_compat_2 class=tabs-scala-version %}
258-
{% tab 'Scala 2' %}
259-
~~~ scala
260-
case class Person private (name: String, age: Int, address: Option[String]) {
261-
...
262-
// Add back the former primary constructor signature
263-
private[Person] def this(name: String, age: Int) = this(name, age, None)
264-
def withAddress(address: Option[String]) = copy(address = address)
265-
}
266-
~~~
267-
{% endtab %}
268-
{% tab 'Scala 3' %}
269-
~~~ scala
224+
{% tabs case_class_compat_2 %}
225+
{% tab 'Scala 3 Only' %}
226+
```scala
270227
case class Person private (name: String, age: Int, address: Option[String]):
271228
...
272229
// Add back the former primary constructor signature
273230
private[Person] def this(name: String, age: Int) = this(name, age, None)
274231
def withAddress(address: Option[String]) = copy(address = address)
275-
~~~
232+
```
276233
{% endtab %}
277234
{% endtabs %}
278235

@@ -286,16 +243,12 @@ The original users can use the case class `Person` as before, all the methods th
286243
287244
The new field `address` can be used as follows:
288245
289-
{% tabs case_class_compat_3 %}
290-
{% tab 'Scala 2 and 3' %}
291246
~~~ scala
292247
// The public constructor sets the address to None by default.
293248
// To set the address, we call withAddress:
294249
val bob = Person("Bob", 21).withAddress(Some("Atlantic ocean"))
295250
println(bob.address)
296251
~~~
297-
{% endtab %}
298-
{% endtabs %}
299252
300253
A regular case class not following this pattern would break its usage, because by adding a new field changes some methods (which could be used by somebody else), for example `copy` or the constructor itself.
301254

0 commit comments

Comments
 (0)