When to use OOP is a bad idea

"OOP is an expensive disaster that must end"

[QUOTE = lead gloss] by the way: the type system of Scala is a peculiar egg-laying woolly bastard - compared to that, Java Generics are a dream of clarity and clarity. And the implicits of Scala will - should that ever find wider distribution - one day ** implicit ** explode a nuclear power plant

You don't have to do everything. Not all luxury is good. [/ QUOTE]

No question about it, there is a lot of “grown” in Scala, without a corresponding type-theoretical basis behind it, which leads to non-orthogonal behavior. However, the problem is dealt with openly and is working intensively on a “clean” version: https://github.com/lampepfl/dotty

Without starting Flamewars again, let's take a short tour of Scala's type system:

Structural types (“Here comes any type that has a method with the following signature”). In my opinion, not necessarily a bad idea, but difficult to combine with other features. Rarely really needed, should be left out.
Path-dependent types: difficult to understand, rarely needed. I prefer to leave it out if simplification is not possible
Type aliases (“By‘ Dictionary ’, I mean Map ”). Useful, hardly problematic. Just makes complicated signatures more readable or reproduces the “function” (for example “City” instead of “String”).
Generic types like in Java: useful if you don't overuse it
Self-type Incredibly useful concept, in Java it can only be simulated insufficiently with the CRTP (as in the Enum class, for example).
Definition-side variances (This can be used to express, for example, whether List is a subclass of List or not): Definitely useful, the user-side variance in Java (e.g. with wildcards) is usually superior. Still needs fine-tuning because complicated type hierarchies can lead to problems.
Abstract type members (similar to generics, but are not part of the signature, but are more of an “internal matter” of the class): Useful every now and then, but difficult to understand and use. No clear rule when to give preference to generic s. I would rather do without it
Singleton classes: Except for the stupid keyword “object” a good idea. The normal criticisms of singletons apply here only to a limited extent and are not as serious as the criticism of the “static” concept (which Scala has abolished via singletons with the variant “companion object”). Package objects can be seen as a further variant of this
Implicits (and related View Bounds): Allows a kind of “type classes” (in some respects more flexible than in Haskell), statically typed “ducktyping” and dependency injection. Definitely one of the best and most powerful concepts in the language, but it's easy to abuse. Definitely useful after fine-tuning the scoping rules.
Specializations: The possibility of using primitives efficiently in the generic environment is only due to the inadequate JVM type system
Manifestos: Reifiable types. Is only due to the inadequate JVM type system (type erasure)
zero: Actually unnecessary, only due to Java compatibility
Traits: Very similar to Java's interfaces with default methods, limited (stateless) multiple inheritance. Very useful, medium abuse potential. In contrast to Java, they can also be “mixed in” directly during the assignment:
Value objects High-performance wrappers that are optimized away by the compiler. Also suggested for Java (possibly in Java 10)
Higher order types: Indispensable in order to be able to map higher abstractions (e.g. from category theory: functors, monads, arrows). Like all generics, they shouldn't be overused (which is currently the case with the Scala collections). Useful when used sparingly, but less in “normal” code and more in libraries. The basic principle is easy to understand, but the details can get hairy. Potential conflicts with variances.

I think most of the ideas are good, and I think that with a little work they can be implemented orthogonally and intuitively. Sometimes the more useful things are taken over from other, more conservative languages ​​(such as definition-side variances in Kotlin).

In Java I could imagine self-types, definition-side variances, manifests, specializations, value objects and implicit conversions, possibly higher-order types and type aliases. Java already has traits and singletons (as single-element enums); these could be expanded accordingly.