So with such proposal we will not be able to decompose logic in inner classes.
If we want to override such composition we will have to use magical names.
I can understand it for classes(jvm reflection), but traits are something that have many “magics” in jvm so I really do not understand such principles for traits.
It makes scala closer to kotlin. But we have chosen scala out of its extensibility(orientation to high level business logic).
I believe scala should be extensible
If scala were “simple” it would be java\kotlin
That’s a good illustration of the point: They don’t override each other, it just looks this way.
Would You explain why trait shadowing makes Scala-3 project unfeasible?
The rules are universal: A type reference p.T consists of a path p and a type name T. It has a denotation, which might refer to a unique symbol, or not. Because p can have an intersection type or union type, it could have several members named T. In that case the denotation of the reference is the intersection (respectively union) of all member denotations. In all this discussion, there’s no place that a type refers to a unique “symbol” a priori (1). But that’s precisely what would be needed to support shadowing.
(1) Also note that in the DOT calculus there’s no notion of “symbol” anywhere, names is all you have got.
Ceylon’s model is to effectively render nested classes as members just like methods etc. and to make them overridable as such! This should alleviate @odersky’s concern:
as well, right? Or did I miss anything big that’d make this not feasible?
Or did I miss anything big that’d make this not feasible?
What you describe looks like virtual classes. It’s been an intensive research area for 15-20 years, stopped about 10 years ago. Why? Because the only formal treatment with a convincing soundness argument
is so restricted as to be unusable. Concretely you can refer to inner classes only via this. So this.C is OK, but x.C is not.
So, yes, people have tried it and several dozen papers were published. It did not work out.
Virtual classes, as they are also called, received a lot of attention in academia, including in the context of Scala, but I’m not aware of an approach that’s both practical and safe/sound. You can get quite close with abstract types and factory methods, but you’ll quickly run into problems that those types cannot safely be used because you don’t know which override (decided at runtime) you’re dealing with. Same problem as MyType.
As far as the examples I’ve seen here, how about one public base type and then a private implementation in each subclass. Private classes don’t cause name clashes.
Has research examined “extension classes” (in analogy to extension methods)? My hunch is that it would be both sound and useful, but probably not worth the complexity budget. (After all, you can express the same thing with a typeclass-like mechanism to bind the outer and “inner” types; your only problem there is visibility unless you have a friend mechanism like C++.)
Empty object is not a big deal, IMO. Inner classes and traits will be stored in extra class files anyway.
So what? You could still use them.
Inner trait of class has implicit reference to outer class which can be made explicit. Visibility of private methods is retained in my scheme. Look at this:
package no_shadowing
class Bfb_InventoryOrderDvi { self =>
import Bfb_InventoryOrderDvi._
def list(): List = new List {
override def outer: Bfb_InventoryOrderDvi = self
}
private def privateOfBfb_InventoryOrderDvi(): Unit = ()
}
class Bfb_InventoryOrderAvi extends Bfb_InventoryOrderDvi { self =>
import Bfb_InventoryOrderAvi._
override def list(): List = new List {
override def outer: Bfb_InventoryOrderAvi = self
}
private def privateOfBfb_InventoryOrderAvi(): Unit = ()
}
object Bfb_InventoryOrderDvi {
trait Default {
protected def outer: Bfb_InventoryOrderDvi
def callerOfBfb_InventoryOrderDvi(): Unit =
outer.privateOfBfb_InventoryOrderDvi()
}
trait List extends Default
trait Card extends Default
trait Lookup extends Default
}
object Bfb_InventoryOrderAvi {
import no_shadowing.{Bfb_InventoryOrderDvi => Super}
trait Default extends Super.Default {
override protected def outer: Bfb_InventoryOrderAvi
def callerOfBfb_InventoryOrderAvi(): Unit =
outer.privateOfBfb_InventoryOrderAvi()
}
trait List extends Default with Super.List
trait Card extends Default with Super.Card
trait Lookup extends Default with Super.Lookup
}
Show me code which works with your scheme, but doesn’t work with my scheme.
I do not undertand what do you try to prove me.
Lets disable shadowing at all(for inner variables etc)
And then I give you example wich will work.
Will it really help you?
I think it is good principle for system languages(‘c’). But it is awful for high level one it is a road to hell )))
AFAIU your main concern was that disabling class shadowing will force you to use extra prefixes/ suffixes:
What I shown is that you do not need that even with class shadowing disabled.
I’m just curious whether your argument (i.e. disabling class shadowing forces to use “magic names”) is valid. IMO you just need some refactoring (that I shown) and class/ trait/ etc names will stay the same.
Sorry, but you have not shown it.
Your proposal not to use inner traits is very doubtful. Are you really trying to prove that inner traits are useless?
Your proposal to use objects is as usful for us as prefixes
Not at all. OTOH, I think that if you change code generator a bit then you don’t need to come up with “magical names” nor do you need substantial changes in client code.
Well, use whatever you want. I still don’t think there’s any serious problem with disallowing class shadowing. However, I would be glad if you prove me otherwise, i.e. pinpoint a problem with my scheme that I’m not aware of.
By “client code” I meant code that uses the generated classes.
I think you’re confusing shadowing with overriding. Class members in Scala can and will be able to be overridden.
What shadowing gives you except for reusing the same name for a potentially completely different thing? Remember that shadowing doesn’t care about types, so for a compiler it doesn’t matter if you shadow a parent class with a child class. You don’t gain extra flexibility from that, AFAIU.