Private Delegated method - kotlin

I am using class delegation in Kotlin and wondering if it is possible to make the delegated method private in Kotlin
interface A{
fun test(name: String)
}
class A1:A{
fun test(name: String): String = name
}
interface C{
fun myTest(name: String)
}
class C1(a:A){
fun myTest(name: String) = a.test(name)
}
class B(a:A): C by C1(a) {
// I can call "mytest" here
fun anotherMethod() = myTest("hi")
//But I want to make "myTest" private
}
val b = B(A1())
//This should not be possible
//b.myTest()

Interface is used to expose functions for public API, if B is A, then it must have a public member test.
You shouldn't implement A if you don't want test() to be available as public member:
class B(val a: A) {
fun anotherMethod() = a.test("hi")
}

Related

smart class to val property inside the class

public val properties for interface does't do smart casting to the object that were set into them.
is there an alternative?
There is an option do declare 2 variables. one public interface and one private instance. but I prefer just one
what I wish to have:
class MyClass{
val myObservable: Observable<Unit> = PublishSubject.create<Unit>()
fun foo(){
myObservable.onNext(Unit) // smart casting doesn't work
}
}
what works but involves boilerplate code
class MyClass{
private val myPublisher = PublishSubject.create<Unit>()
val myObservable: Observable<Unit> = myPublisher
fun foo(){
myPublisher.onNext(Unit)
}
}

Access delegate object from a method

Consider the following Kotlin code:
class Derived(n1: String, n2:String) : Teacher by TeacherImp(),Person by PersonImpl(n1, n2) {
// desire to call method of PersonImp object... possible??
}
Is there any way to access the delegate object instances?
Consider if the derived class wants to access a method of a delegate.
You can save the delegate(s) into private immutable property(s) - for example:
interface Teacher {
fun sayHelloTeacher() = println("Teacher hello")
}
interface Person {
fun sayHelloPerson() = println("Person hello")
}
class TeacherImp : Teacher {
fun sayHelloTeacherImp() = println("TeacherImp hello")
}
class PersonImp(val n1: String, val n2: String) : Person {
fun sayHelloPersonImp() = println("PersonImp hello $n1 $n2")
}
class Derived private constructor(private val t: TeacherImp, private val p: PersonImp) :
Teacher by t, Person by p {
constructor(n1: String, n2: String) : this(TeacherImp(), PersonImp(n1, n2))
init {
sayHelloPerson()
sayHelloTeacher()
t.sayHelloTeacherImp()
p.sayHelloPersonImp()
}
}
fun main(args: Array<String>) {
Derived("first", "second")
}
With this implementation the only public constructor is the same as the original, and which calls the private constructor that stores the actual objects.
Note: With reflection it may possible to access them without the extra constructor, but I think this is a straightforward solution to your problem.

What are the advantages of a companion object over a plain object?

Kotlin code like this:
class Foo {
companion object {
fun a() : Int = 1
}
fun b() = a() + 1
}
can trivially be changed to
object FooStatic {
fun a() : Int = 1
}
class Foo {
fun b() = FooStatic.a()
}
I'm aware that the companion object can be used to allow use as real java static function, but are there any other advantages to using the companion object?
One of the key differences is visibility of the members.
In a companion object, visibility to the containing class is as-if the members were part of the class - this is not the case for a raw object.
The example below shows that you cant use an "object" to implement private static internals of a class.
package com.example
class Boo {
companion object Boo_Core {
// Public "static" call that non-Boo classes should not be able to call
fun add_pub(a:Int) = a+1;
// Internal "static" call that non-Boo classes should not be able to call
private fun add_priv(a:Int) = a+1;
}
// OK: Functions in Boo can call the public members of the companion object
fun blah_pub(a:Int) = add_pub(a)
// OK: Functions in Boo can call the private members of the companion object
fun blah_priv(a:Int) = add_priv(a)
}
//Same idea as the companion object, but as an "object" instead.
object Foo_Core {
fun add_pub(a:Int) = a+1
private fun add_priv(a:Int) = a+1;
}
class Foo {
// OK Foo can get Foo_Cors add_pub
fun blah_pub(a:Int) = Foo_Core.add_pub(a);
// ERROR: can not get to add_priv
// fun blah_priv(a:Int) = Foo_Core.add_priv(a);
}
class AnInterloper {
// OK Other classes can use public entries in Foo.
fun blah_foo_pub(a:Int) = Foo_Core.add_pub(a);
// ERROR Other classes can use public entries in Foo.
// fun blah_foo_priv(a:Int) = Foo_Core.add_priv(a);
// OK: Other classes can use public Boo classes
fun blah_boo_pub(a:Int) = Boo.add_pub(a);
// ERROR: Other classes can not use private Boo classes
// fun blah_boo_priv(a:Int) = Boo.add_priv(a);
}

Kotlin cannot access protected abstract method

I have the following classes structure:
abstract class Abstr{
protected abstract fun m()
}
class Child : Abstr(){
private val subChild: Abstr = Child()
override fun m() = subChild.m()// Error:(12, 18) Kotlin: Cannot access 'm': it is protected in 'Abstr'
}
I got an exception Kotlin: Cannot access 'm': it is protected in 'Abstr'
It little bit confusing, because the same structure is legal for java.
According to kotlin docs
protected — visible inside this class only + visible in subclasses too;
Is it bug or expected behavior?
It is designed behavior
Protected modifier in Kotlin similar to Java, but has additional restrictions.
Protected in Java:
Visible for inheritance
Visible in package
Protected in Kotlin:
Visible for inheritance
So, according to the code in question we cannot access protected method
class Child : Abstr(){
private val subChild: Abstr = Child()
override fun m() = subChild.m() //Trying to access not inherited method
}
There is similar restriction in Java, when we trying to access protected member from another package:
// FILE: a/SuperClass.java
package a;
public class SuperClass {
protected void superFunction() {}
}
// FILE: b/ChildClass.java
package b;
public class ChildClass extends SuperClass {
void testFunction() {
((SuperClass) new ChildClass()).superFunction(); // ERROR: superFunction() has protected access in a.SuperClass
}
}
There is answer in issue tracker from Kotlin team:
https://youtrack.jetbrains.com/issue/KT-21048
The current behavior is by design.
By calling subChild.m() you're trying to access an instance of Abstr from outside the object, so protected access prevents you from doing this.
Let me show you a short example to clarify the case
abstract class ParentCl {
protected var num = 1
protected open fun m(){
}
}
class ChildCl : ParentCl() {
private val a0 : ParentCl = ChildCl()
override fun m() {
super.m() // 1-st case
num = 2 // 2-nd case
a0.m() // 3-rd case
}
}
You're calling the protected ParentCl's fun from the child class. It will work fine.
You're modifying of protected variable from the child class. It will work fine.
You're calling the protected fun outside the context of the child class. This will not work.
Depends on what was your goal there are two solutions:
If you wanted to call m() from ParentCl you need to change the visibility from protected to internal or public.
If you wanted to call m() from the child class you need to declare the variable without the explicit type of its parent: private val subChild = Child().
Note: in case you will use m() from other children of ParentCl you need to enlarge the visibility scope inside child class: public override fun m() {...}
It's possible a bug.
When i added {} everything became ok.
abstract class Abstr{
protected abstract fun m()
}
class Child : Abstr(){
private val subChild: Abstr = Child()
override fun m() {
subChild.m() // Compiles fine
}
}
Create issue on https://discuss.kotlinlang.org/
or write on Slack
http://slack.kotlinlang.org/
protected — same as private + visible in subclasses too;
abstract class BaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(getLayoutResId())
}
protected open fun getPageTitle() = SpannableString(getString(R.string.app_name))
}
In your sub class
class EditProfileActivity : BaseActivity() {
override fun getPageTitle(): SpannableString = SpannableString(getString(R.string.edit_profile))
}
See the doc for more details
visibility-modifiers
Classes

How to overcome "same JVM signature" error when implementing a Java interface?

With the code below, I am getting the following error in IntelliJ IDEA 13.1.6 and Kotlin plugin 0.11.91.AndroidStudio.3:
Platform declaration clash: The following declarations have the same JVM signature (getName()Ljava/lang/String;):
• public open fun getName(): kotlin.String?
• internal final fun <get-name>(): kotlin.String?
Java class, JavaInterface.java:
public interface JavaInterface {
public String getName();
}
Kotlin class, KotlinClass.kt
public class KotlinClass(val name: String?) : JavaInterface
I've tried overriding the 'getter' method by
adding override fun getName(): String? = name, but that produces the same error.
I can see one workaround by doing this instead:
public class KotlinClass(val namePrivate: String?) : JavaInterface {
override fun getName(): String? = namePrivate
}
But in my real-world case I have a number of properties to implement and need setters too. Doing this for each property doesn't seem very Kotlin-ish. What am I missing?
Making that variable private solves the problem.
public class KotlinClass(private val name: String?) : JavaInterface
You could use #JvmField for instructs the compiler not generate getter/setter, and you can implement your setters and getters. With this your code work well in Java (as attribute getter/setter) and Kotlin as property
Example:
JAVA:
public interface Identifiable<ID extends Serializable>
{
ID getId();
}
KOTLIN:
class IdentifiableImpl(#JvmField var id: String) :Identifiable<String>
{
override fun getId(): String
{
TODO("not implemented")
}
}
The annotation feature of Kotlin named #JvmName will solve the duplication problem in Java and Kotlin when having the same signature.
fun function(p: String) {
// ...
}
// Signature: function(Ljava/lang/String)
With the use of JvmName will be:
#JvmName("functionOfKotlin")
fun function(p: String) {
// ...
}
// Signature: functionOfKotlin(Ljava/lang/String)
IMHO most readable combination is field + explicit interface implementation by the single-expression function (combination of #Renato Garcia's and #Steven Spungin's answers):
Java:
public inteface SomeInterface {
String getFoo();
}
Kotlin:
class Implementation(#JvmField val foo: String) : SomeInterface {
override fun getFoo() = foo
}
Another work-around is to declare the properties in an abstract Kotlin class, then write a small java class that extends KotlinClass and implements JavaInterface.
// JavaInterface.java
public interface JavaInterface {
int getFoo();
void setFoo(int value);
}
// KotlinClass.kt
abstract class KotlinClass(open var foo : Int = 0) {
}
// JavaAdapter.java
class JavaAdapter extends KotlinClass implements JavaInterface {
// all code in KotlinClass, but can't implement JavaInterface there
// because kotlin properties cannot override java methods.
}
We have found that to use the same names without clashing, the ctor args must be private AND you must still override the interfaces methods. You don't need any additional backing fields. Also, your expression body assignment will not recurse, so you can safely use that syntax.
Java Interface
interface IUser {
String getUserScope();
String getUserId();
}
Kotlin Class
class SampleUser(private val userScope: String, private val userId: String) : IUser {
override fun getUserId() = userId
override fun getUserScope() = userScope
}
If you have direct control over the interface then the best approach is to write the interface in Kotlin. You can then write your class
public class KotlinClass(override val name: String?) : KotlinInterface
and still reference it from any Java code using the same interface as before. This looks a lot neater than setting all the properties to private and overriding the get function. Obviously if you can't migrate the interface to Java because you don't own it then that seems to be the only solution.
public interface JavaInterface {
public String getName();
}
public class KotlinClass(val namePrivate: String?) : JavaInterface {
private var name = namePrivate
override fun getName(): String? {
return name
}
}
Rename the variable to something else, or make it private if u dont want it to be public.
convert function to property instead of initializing property from a function.
for ex:
fun getCountriesList(): List<Country> {
val countries = mutableListOf<Country>()
countries.add(Country("in", "+91", "India", R.drawable.indian_flag))
countries.add(Country("us", "+1", "United States",R.drawable.us_flag))
return countries
}
to
val countriesList: List<Country>
get() {
val countries = mutableListOf<Country>()
countries.add(Country("in", "+91", "India", R.drawable.indian_flag))
countries.add(Country("us", "+1", "United States", R.drawable.us_flag))
return countries
}