Why protected var is KProperty and public/private var is KMutableProperty? - kotlin

In each of the following cases I have some mutable var properties. According to Javadocs mutable properties are represented by KMutableProperty but in these examples protected property is represented by KProperty class. Why is that so?
class FooA {
var publicProp: String? = null
protected var protectedProp: String? = null
private var privateProp: String? = null
fun foo() {
val a = ::publicProp
val b = ::protectedProp
val c = ::privateProp
}
}
open class FooB {
var publicProp: String? = null
protected var protectedProp: String? = null
private var privateProp: String? = null
fun foo() {
val a = ::publicProp
val b = ::protectedProp
val c = ::privateProp
}
}
class Bar : FooB() {
fun bar() {
val a = ::publicProp
val b = ::protectedProp
}
}
Type hints from IDEA

Related

How to solve this strong dependency between those classes?

I have two classes A and B.
Class A has several properties. One of them are an instance of class B.
At some point in the main function I will define an instance a of A. I will need to do some computation on its property of type B.
This computation, however, needs another property of a.
The result is a.property3.computation(a.property1,someValue). I think it's ugly.
Here is some "pseudo-code" (in Kotlin but I am facing the same problem using other languages as well):
class B {
val property : Map<String,Int>
fun computation(val parameter1: Int, val parametre2: Double) : Int {
//doing some computation
return result
}
}
class A {
var property1 : Int
var property2 : Stirng
var property3 : B
}
fun main (){
val someValue = 0.4 //It's here to show the idea that the function `computation` needs also some other arguments that does not come from `A`'s propery
val a = A()
val result = a.property3.computation(a.property1,someValue) // here is the line that bothers me !
}
I think you should use Builder design pattern to remove computation function from B class like this:
class B {
val properties : MutableMap<String,Int> = HashMap()
fun setProperty(name: String, value: Int) {
this.properties[name] = value
}
}
class A {
var property1 : Int = 0
var property2 : String = ""
var property3 : B = B()
}
class Calculator(builder: Builder) {
private val property1 = builder.property1
private val someValue = builder.someValue
private val properties = builder.properties
companion object {
fun builder() = Builder()
}
fun computation() : Int {
//doing some computation
val result = property1 + someValue.toInt() + properties.getOrDefault("value", 0)
return result
}
class Builder {
var property1: Int = 0
var someValue: Double = 0.0;
var properties : MutableMap<String,Int> = HashMap()
fun property1(property1: Int): Builder {
this.property1 = property1
return this
}
fun someValue(someValue: Double): Builder {
this.someValue = someValue
return this
}
fun properties(properties : Map<String,Int>): Builder {
this.properties.putAll(properties);
return this
}
fun build(): Calculator {
return Calculator(this)
}
}
}
fun main (){
val someValue = 0.4 //It's here to show the idea that the function `computation` needs also some other arguments that does not come from `A`'s propery
val a = A()
a.property1 = 10
a.property3.setProperty("value", 20)
val result = Calculator.builder()
.properties(a.property3.properties)
.property1(a.property1)
.someValue(someValue)
.build()
.computation()
println(result)
}
May be you want this?
fun main (){
val someValue = 0.4
val a = A()
val result = with(a) {
property3.computation(property1,someValue)
}
}

I am trying to add a code from a book I am following to an existing code I am writing

Open PodcastActivity.kt and add the following lines to the top of the class. This is the question
this is the code I am adding
private val searchViewModel by viewModels()
private lateinit var podcastListAdapter: PodcastListAdapter
This is where I am adding it to
class PodcastActivity : AppCompatActivity() {
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// 1
val inflater = menuInflater
inflater.inflate(R.menu.menu_search, menu)
// 2
val searchMenuItem = menu.findItem(R.id.search_item)
val searchView = searchMenuItem?.actionView as SearchView
// 3
val searchManager = getSystemService(Context.SEARCH_SERVICE)
as SearchManager
// 4
searchView.setSearchableInfo(
searchManager.getSearchableInfo(componentName)
)
return true
setupToolbar()
}
private fun performSearch(term: String) {
val itunesService = ItunesService.instance
val itunesRepo = ItunesRepo(itunesService)
itunesRepo.searchByTerm(term) {
Log.i(Companion.TAG, "Results = $it")
}
}
private fun handleIntent(intent: Intent) {
if (Intent.ACTION_SEARCH == intent.action) {
val query = intent.getStringExtra(SearchManager.QUERY) ?: return
performSearch(query)
}
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
handleIntent(intent)
}
companion object {
private const val TAG = "PodcastActivity"
}
private fun setupToolbar() {
setSupportActionBar(toolbar)
}
}

Cannot infer a type for this parameter please specify it explicitly?

I have recently developed android app using Kotlin but I am getting the following error
Cannot infer a type for this parameter. Please specify it explicitly
below screenshot of the error
below my class where I am getting error
class AddBookingActivity : AppCompatActivity() {
#BindView(R.id.attendees_recycler_view)
internal var mAttendeeRecyclerView: RecyclerView? = null
#BindView(R.id.start_time_edit_text)
internal var mStartTime: EditText? = null
#BindView(R.id.end_time_edit_text)
internal var mEndTime: EditText? = null
private var mAttendeeName: EditText? = null
private var mAttendeeEmail: EditText? = null
private var mAttendeePhoneNumber: EditText? = null
private var mAttendeeAdapter: AttendeeAdapter? = null
private var mAlertDialog: AlertDialog? = null
private val mAttendeeItemList = ArrayList<AttendeeItem>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_add_booking)
ButterKnife.bind(this)
mAttendeeRecyclerView!!.layoutManager = LinearLayoutManager(this)
mAttendeeAdapter = AttendeeAdapter(this)
mAttendeeAdapter!!.setAttendeeList(mAttendeeItemList)
mAttendeeRecyclerView!!.adapter = mAttendeeAdapter
}
#OnClick(R.id.toolbar_back_button)
internal fun onBackButtonClicked() {
onBackPressed()
}
#OnClick(R.id.start_time_edit_text)
internal fun onStartTimeClicked() {
showTimePickerDialog(mStartTime)
}
#OnClick(R.id.end_time_edit_text)
internal fun onEndTimeClicked() {
showTimePickerDialog(mEndTime)
}
#OnClick(R.id.fab_add_attendee)
internal fun onAddAttendeeClicked() {
val inflater = this.layoutInflater
val dialogView = inflater.inflate(R.layout.add_attendee_view, null)
mAttendeeName = dialogView.findViewById(R.id.attendee_name)
mAttendeeEmail = dialogView.findViewById(R.id.attendee_email)
mAttendeePhoneNumber = dialogView.findViewById(R.id.attendee_phone_number)
mAlertDialog = AlertDialog.Builder(this, R.style.AlertDialog)
.setTitle("Input attendee details")
.setPositiveButton("Add") { dialog, which ->
val item = AttendeeItem()
item.name = mAttendeeName!!.text.toString()
item.email = mAttendeeEmail!!.text.toString()
item.phoneNumber = mAttendeePhoneNumber!!.text.toString()
mAttendeeItemList.add(item)
mAttendeeAdapter!!.setAttendeeList(mAttendeeItemList)
mAttendeeAdapter!!.notifyItemInserted(mAttendeeItemList.size)
}
.setNegativeButton("Cancel", null)
.setView(dialogView).create()
mAlertDialog!!.show()
}
private fun showTimePickerDialog(editText: EditText?) {
val myCalender = Calendar.getInstance()
val hour = myCalender.get(Calendar.HOUR_OF_DAY)
val minute = myCalender.get(Calendar.MINUTE)
#SuppressLint("DefaultLocale")
val myTimeListener = { view, hourOfDay, minute1 ->
if (view.isShown()) {
myCalender.set(Calendar.HOUR_OF_DAY, hourOfDay)
myCalender.set(Calendar.MINUTE, minute1)
editText!!.setText(String.format(String.format("%s:%s", hourOfDay.toString(), minute1.toString())))
}
}
val timePickerDialog = TimePickerDialog(this, android.R.style.Theme_Holo_Light_Dialog_NoActionBar, myTimeListener, hour, minute, true)
timePickerDialog.setTitle("Choose hour:")
timePickerDialog.window!!.setBackgroundDrawableResource(android.R.color.transparent)
timePickerDialog.show()
}
}
You have to specify the interface to help Kotlin compiler:
#SuppressLint("DefaultLocale")
val myTimeListener = TimePickerDialog.OnTimeSetListener { view, hourOfDay, minute1 ->
if (view.isShown()) {
myCalender.set(Calendar.HOUR_OF_DAY, hourOfDay)
myCalender.set(Calendar.MINUTE, minute1)
editText!!.setText(String.format(String.format("%s:%s", hourOfDay.toString(), minute1.toString())))
}
}

kotlin.UninitializedPropertyAccessException: lateinit property salesGST Model class has not instalized

Json Data parse using Retrofit2 and rxjav2. then its give error of lateinit Property of salesGST :
"kotlin.UninitializedPropertyAccessException: lateinit property salesGST has not been initialized"
Model Class SalesGSTList in JSONObject key success after SalesGST data in ArrayList.
class SalesGSTList {
val success : String = ""
lateinit var salesGST: ArrayList<SalesGST>
}
JSON Key declare in SalesGST.
class SalesGST {
var FYearID : Int = 0
var Cmp_Name : String? = ""
var GSTIN : String? = ""
var FirmName : String? = ""
}
Parsing Json data Display in Textview and TableLayout. when data Subscribe then give error.
sales.kt
class Sales : AppCompatActivity() {
internal lateinit var api : APIInterface
private var compositeDisposable : CompositeDisposable? = null
private var salesGST : SalesGST? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sales)
compositeDisposable = CompositeDisposable()
fetchYearData()
}
private fun fetchYearData(){
val retrofit = APIClient.apIClient
if (retrofit != null) {
api = retrofit.create(APIInterface::class.java)
}
/*compositeDisposable!!.add(api.getSalesGSTData(cid,fid,fDate,tDate)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { displaySalesGSTData(it.salesGST) })*/
compositeDisposable!!.add(api.getSalesGSTData(1,1,"04/01/2018","31/03/2019")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe( {
displaySalesGSTData(it.salesGST) },
{
Toast.makeText(this,it.message,Toast.LENGTH_LONG).show()
}))
}
private fun displaySalesGSTData(salesGSt : List<SalesGST>) {
salesGST = SalesGST()
tvSalesCompanyName.setText(salesGST!!.Cmp_Name)
tvGSTIN.setText(salesGST!!.GSTIN)
val rowHeader = TableRow(this#Sales)
rowHeader.setBackgroundColor(Color.parseColor("#c0c0c0"))
rowHeader.setLayoutParams(TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT))
val headerText = arrayOf<String>("Sr.No.", "Invoice Type", "Bill No.", "Bill Date", "Firm Name", "GST NO","TAX Total","CGST","SGST","IGST","Net Amount")
for (c in headerText)
{
val tv = TextView(this#Sales)
tv.setLayoutParams(TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT,
TableRow.LayoutParams.WRAP_CONTENT))
tv.setGravity(Gravity.CENTER)
// tv.setBackgroundResource(R.drawable.table_header)
tv.setTextColor(Color.parseColor("#3F51B5"))
tv.setTextSize(18F)
tv.setPadding(5, 5, 5, 5)
tv.setText(c)
rowHeader.addView(tv)
}
tableMarks.addView(rowHeader)
for (j in 0 until salesGSt.size)
{
var fName : String = salesGSt[j].FirmName!!
var invoice : String = salesGSt[j].InvoiceType!!
var bill_no : String = salesGSt[j].ChallanNo!!
var bill_date : String = salesGSt[j].ChallanDate!!
var gst_no : String = salesGSt[j].PartyGST!!
var tax_total : String = salesGSt[j].TaxTotal!!
var cgst : String = salesGSt[j].CGSTTotal!!
var igst : String = salesGSt[j].IGSTTotal!!
var sgst : String = salesGSt[j].SGSTTotal!!
var net_amount : String = salesGSt[j].ChallanAmount!!
var sr : Int = j
// dara rows
val row = TableRow(this#Sales)
row.setLayoutParams(TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT))
val colText = arrayOf<String>(sr.toString(),(invoice), bill_no, bill_date, fName, gst_no,tax_total,cgst,sgst,igst,net_amount)
for (text in colText)
{
val tv = TextView(this#Sales)
tv.setLayoutParams(TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT,
TableRow.LayoutParams.WRAP_CONTENT))
tv.setGravity(Gravity.CENTER)
// tv.setBackgroundResource(R.drawable.table_shape)
tv.setTextSize(18F)
tv.setTextColor(Color.parseColor("#000000"))
tv.setPadding(5, 5, 5, 5)
tv.setText(text)
row.addView(tv)
}
tableMarks.addView(row)
}
}
}
Interface
#GET("SalesGST.php")
fun getSalesGSTData(#Query("cid") cid : Int,#Query("fid") fid : Int,#Query("fd") fd : String,#Query("td") td : String) : Observable<SalesGSTList>
This error is really clear. You try to use your variable salesGST before you initialized it.
I guess this is coming from here:
class SalesGSTList {
val success : String = ""
// salesGST expects to be initialize soon and is never initialized
lateinit var salesGST: ArrayList<SalesGST>
}
You should either do a lazy initialization of salesGST, or set it as:
var salesGST: ArrayList<SalesGST>? = null

Kotlin - Factory Function for Class with Private Constructor

In Kotlin, is it possible to have a factory function that creates an instance of a class with a private constructor?
My goal is to enforce the factory function to be used and to prevent instantiation via the class's constructor.
Example:
// factory function, valid
val myInstance = myClassOf()
// class instantiation, invalid
val myInstance = MyClass()
I'm trying to mimic the behavior of some of the built-in factory functions like intArrayOf(), e.g.
// works
val myIntArray = intArrayOf()
// not possible as IntArray has a private constructor
val myIntArray = IntArray()
You can use companion object in this way:
class MyClass private constructor() {
companion object {
operator fun invoke() = MyClass()
}
}
val myInstance = MyClass() // Calls the factory function invoke()
Name the factory function if it has a special meaning. For example:
class MyClass private constructor(values: List<String>) {
companion object {
fun of(vararg values: String) = MyClass(values.toList())
}
}
val myInstance = MyClass.of("first", "second")
You can do something like this:
import MyClass.Companion.myClassOf
class MyClass private constructor() {
companion object {
fun myClassOf() = MyClass()
}
}
//val myInstance1 = MyClass() // not allowed
val myInstance2 = myClassOf()
Try Builder instead.
class FoodOrder private constructor(
val bread: String?,
val condiments: String?,
val meat: String?,
val fish: String?) {
data class Builder(
var bread: String? = null,
var condiments: String? = null,
var meat: String? = null,
var fish: String? = null) {
fun bread(bread: String) = apply { this.bread = bread }
fun condiments(condiments: String) = apply { this.condiments = condiments }
fun meat(meat: String) = apply { this.meat = meat }
fun fish(fish: String) = apply { this.fish = fish }
fun build() = FoodOrder(bread, condiments, meat, fish)
}
}
Reference: https://www.baeldung.com/kotlin-builder-pattern