Why we cannot mark the visibility of a class as "protected" in kotlin? - class

I am new to kotlin I have been learning about inheritance in kotlin recently, and then I realised that we cannot mark the visibility of a class as "protected". Correct me if i am wrong, or is there any other way to make a class protected ?

You can mark protected only parts of classes, so that they become accessible only from the derived classes. You can mark protected a member property, a member function or a nested class:
open class X {
protected val v: SomeType = someValue
protected fun f() { }
protected class Y { ... }
}
But you cannot mark protected anything that does not belong to a class (e.g. a top-level class or function), because the modifier would make no sense: a top-level entity is not subject to inheritance, thus there can be no derived class that would access it.

Related

Make constructor parameters public in subclass

I want the protected fields of a class to be made publicly visible in a subclass:
class MyClass(protected val someDao: SomeDao)
class TestMyClass extends MyClass(mock[SomeDao])
Now I want to access someDao like so:
val testClass = new TestMyClass
testClass.someDao
I've read that in Java and Scala access modifiers can be broadened but not restricted in subclasses (although these are just constructor parameters, not private fields per se). How can I achieve that in this example?
EDIT:
The answers provided suggest making someDao public in the base class. This is not what I want. I want it to remain private, but just change its visibility to public in the TestMyClass class.
As far as I know, an overriden val cannot access the super implementation.
If you can modify the base class, one solution is to explicitely define an accessor method, which can be overriden; something like this:
class MyClass(_someDao: SomeDao) {
protected def someDao = _someDao
}
class TestMyClass extends MyClass(mock[SomeDao]) {
override def someDao = super.someDao
}
If you cannot change the base class, one workaround would be to define a public accessor method with a different name:
class MyClass(protected val someDao: SomeDao)
class TestMyClass extends MyClass(mock[SomeDao]) {
def someDao2 = someDao
}
Add var or val to parameters declaration:
class MyClass(val someDao: SomeDao)
In this case only getter function will be generate for someDao field. So when you write testClass.someDao you retrieve not the someDao as field you use their getter function.
Good example about visibility of class parameters in Scala demostrated at this article.
Regarding to your last updates
Set package scope for parameter declaration:
class MyClass(private[lastPackageOfSomeDao] val someDao: SomeDao)

autofac Register closed subclasses of abstract open generic

public class Sub1 : Base<SomeClass>
{
// for sake of getting injection to work, not injecting anything in ctor
public Sub1() {}
....
}
public class Sub2 : Base<SomeOtherClass>
{
// for sake of getting injection to work, not injecting anything in ctor
public Sub2() {}
....
}
public abstract class Base<T>
{
// abstract, so no ctor
....
}
I tried the following but I'm getting the exception listed below. Notice it the exception references the Base abstract class. What am I missing?
builder.RegisterAssemblyTypes(typeof(Base<>).Assembly)
.Where(t => t.IsSubclassOf(typeof(Base<>))).AsClosedTypesOf(typeof(Base<>)).InstancePerDependency();
No constructors on type 'Base`1[SomeClass]' can be found with the constructor finder 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder'.
I think you mixed with generic and non generic abstract class registrations.
You have generic abstract class. Therefore your register should be like this:
builder.RegisterAssemblyTypes(typeof(Base<>).Assembly).AsClosedTypesOf(typeof(Base<>)).InstancePerDependency();

What's the implication of protected keywords in class definition in Scala?

I'm learning Scala by working the exercises from the book "Scala for the Impatient". One exercise asks that:
The file Stack.scala contains the definition class Stack[+A]
protected (protected val elems: List[A])
Explain the meaning of the protected keywords.
Can someone help me understand this? protected obviously makes sense for member variables but what implication does it have in a class definition?
In Scala, writing
class Stack[+A](elems: List[A])
also implements a default constructor. If you know Java, then in Java this would be something like
class Stack<A> {
private List<A> elems;
public Stack<A>(List<A> elems){this.elems = elems;}
}
Now, you have two protected keywords in your example:
protected val elems: List[A]
protected (/*...*/)
The first makes the variable elems protected, meaning it can only be accessed (and shadowed) by subclasses of Stack[+A].
The second makes the constructor protected, meaning that a new Stack instance can only be created by subclasses of Stack[+A].
Again, the equivalent Java code would be something like
class Stack<A> {
protected List<A> elems;
protected Stack<A>(List<A> elems){this.elems = elems;}
}

Merging of custom and compiler generated companion objects for a case class. What are the merging rules?

I just tried out this code below and it worked as expected. It prints 1.
Now, my problem is that I don't understand what is going on under the hood.
How can a case class have two companion objects (One generated by the compiler and one written by me) ? Probably it cannot. So they must be merged somehow under the hood. I just don't understand how are they merged ? Are there any special merging rules I should be aware of ?
Is it so that, if the set of definitions defined in both companion objects are disjoint then the set of definitions in the resulting case class is simply the union of two disjoint sets ? I would think this is how they are merged, but I am not sure. Can someone please confirm whether this merging rule is the one that is implemented in the Scala compiler? Or is there something extra to it ?
More specifically, what are the rules by which the compiler generated companion object and my companion object are merged ? Are these rules specified somewhere ?
I have not really seen this topic discussed in the few Scala books I have - perhaps too superficially - read.
object A{
implicit def A2Int(a:A)=a.i1
}
case class A(i1:Int,i2:Int)
object Run extends App{
val a=A(1,2)
val i:Int=a
println(i)
}
I'm not aware of where the algorithm for merging automatic and explicit companion objects is described or documented (other than the compiler source) but by compiling your code and then examining the generated companion object (using javap), we can see what the differences are (this is with scala 2.10.4).
Here's the companion object generated for the case class (without your additional companion object):
Compiled from "zip.sc"
public final class A$ extends scala.runtime.AbstractFunction2<Object, Object, A> implements scala.Serializable {
public static final A$ MODULE$;
public static {};
public A apply(int, int);
public scala.Option<scala.Tuple2<java.lang.Object, java.lang.Object>> unapply(A);
public java.lang.Object apply(java.lang.Object, java.lang.Object);
public final java.lang.String toString();
}
After adding your companion object, here's what is generated:
Compiled from "zip.sc"
public final class A$ implements scala.Serializable {
public static final A$ MODULE$;
public static {};
public A apply(int, int);
public scala.Option<scala.Tuple2<java.lang.Object, java.lang.Object>> unapply(A);
public int A2Int(A);
}
The differences in the generated companion object caused by the explicit companion object definition appear to be:
it no longer extends AbstractFunction2
it no longer has the factory method (apply) related to bullet 1
it no longer overrides the toString method (I suppose you are expected to supply one, if needed)
your A2Int method is added
If the case class is changed to an ordinary class (along with minimal changes required to get it to compile), the result is the following:
Compiled from "zip.sc"
public final class A$ {
public static final A$ MODULE$;
public static {};
public A apply(int, int);
public int A2Int(A);
}
So it seems that if you declare your own companion object, at least in this simple example, the effect is that your new method is added to the companion object, and some of it's implementation and functionality are lost as well. It would be interesting to see what would happen if we tried to override some of the remaining auto-generated stuff, but there's not much left, so that in general is unlikely to cause conflict.
Some of the benefits of case classes are unrelated to the generated code, such as making the class variables public without having to explicitly add the 'val' keyword. Here's the modified source code for all 3 decompiled examples above.
version 1 (no explicit companion object):
case class A(i1:Int,i2:Int)
version 2 is your original version.
version 3 (no case-class):
object A {
implicit def A2Int(a:A)=a.i1
def apply(a:Int,b:Int):A = new A(a,b)
}
class A(val i1:Int,val i2:Int)
object Run extends App{
import A._
val a=A(1,2)
val i:Int=a
}
In version 3, we need to add val to class A parameters (otherwise they're private), and we have to either add the factory method to our companion object, or use the 'new' keyword when creating an instance of A(1,2).

Private and protected constructor in Scala

I've been curious about the impact of not having an explicit primary constructor in Scala, just the contents of the class body.
In particular, I suspect that the private or protected constructor pattern, that is, controlling construction through the companion object or another class or object's methods might not have an obvious implementation.
Am I wrong? If so, how is it done?
You can declare the default constructor as private/protected by inserting the appropriate keyword between the class name and the parameter list, like this:
class Foo private () {
/* class body goes here... */
}
Aleksander's answer is correct, but Programming in Scala offers an additional alternative:
sealed trait Foo {
// interface
}
object Foo {
def apply(...): Foo = // public constructor
private class FooImpl(...) extends Foo { ... } // real class
}