2015-06-25 18 views
9

tôi tạo ra một Kotlin-class với một thuộc tính lớp, mà tôi muốn khởi tạo trong constructor:Kotlin: Khởi tạo thuộc tính lớp trong constructor

public class TestClass { 

    private var context : Context? = null // Nullable attribute 

    public constructor(context : Context) { 
     this.context = context 
    } 

    public fun doSomeVoodoo() { 
     val text : String = context!!.getString(R.string.abc_action_bar_home_description) 
    } 
} 

Đáng tiếc là tôi đã tuyên bố các thuộc tính như Nullable với biểu tượng "? " ký, mặc dù thuộc tính sẽ được khởi tạo trong hàm tạo. Khai báo thuộc tính này là thuộc tính Nullable làm cho nó luôn luôn cần thiết để buộc một giá trị NonNull với "!!" hoặc để cung cấp kiểm tra Null với "?".

Có cách nào để tránh điều này, nếu thuộc tính lớp sẽ được khởi tạo trong hàm tạo không? Tôi muốn đánh giá cao một giải pháp như thế này:

public class TestClass { 

    private var context : Context // Non-Nullable attribute 

    public constructor(context : Context) { 
     this.context = context 
    } 

    public fun doSomeVoodoo() { 
     val text : String = context.getString(R.string.abc_action_bar_home_description) 
    } 
} 
+0

Ví dụ thứ hai đang hợp tác với Kotlin 0.12.213. Bạn đang sử dụng phiên bản Kotlin nào? – D3xter

+0

Nó hoạt động. Tôi đã sử dụng 0,12,613. Nhưng tôi nghĩ, tôi đã làm điều gì sai. Lấy làm tiếc! – Christopher

+0

Có nhiều trường hợp khả dụng hơn, tôi đã thêm câu trả lời cho phạm vi phủ sóng hoàn chỉnh. –

Trả lời

11

Nếu điều duy nhất bạn đang làm trong các nhà xây dựng là một bài tập, sau đó bạn có thể sử dụng Constructor tiểu học với một tài sản tư nhân.

ví dụ:

public class TestClass(private var context: Context) { 

    public fun doSomeVoodoo() { 
    val text = context.getString(R.string.abc_...) 
    } 
} 
+1

oh, tuyệt! Tôi không biết điều đó! – Christopher

14

Như đã trình bày bởi D3xter bạn có tùy chọn thiết lập nó trong constructor. Bạn cũng có các tùy chọn khác. Ở đây tất cả họ đều ...

Tạo tài sản trong các nhà xây dựng (theo @ D3xter), đây là trường hợp phổ biến nhất đối với tài sản đơn giản khởi tạo trực tiếp bởi các nhà xây dựng chính:

class TestClass(private val context: Context) { 
    fun doSomeVoodoo() { 
     val text : String = context.getString() 
    } 
} 

Bạn có thể khai báo thuộc tính val và không khởi tạo nó, giả sử tất cả các nhà thầu có thể thực sự khởi tạo nó (theo ví dụ thứ hai của bạn trong câu hỏi đang được hỏi). này là bình thường khi bạn có nhiều hơn một nhà xây dựng có thể khởi tạo một giá trị khác nhau:

public class TestClass { 
    private val context: Context 

    public constructor(context : Context) { 
     this.context = context 
    } 

    // alternative constructor 
    public constructor(pre: PreContext) { 
     this.context = pre.readContext() 
    } 

    public fun doSomeVoodoo() { 
     val text : String = context.getString() 
    } 
} 

Bạn có thể vượt qua trong các thông số nhà xây dựng mà không phải là tờ khai tài sản, và sau đó sử dụng những người trong khởi tạo tài sản. này là phổ biến khi bạn có khởi tạo phức tạp hơn hoặc cần phải sử dụng tài sản được giao:

class TestClass(context: PreContext) { 
    private val context : Context by lazy { context.readContext() } 
    private val other: List<Items> = run { 
     context.items.map { it.tag }.filterNotNull() 
    } 
    private val simpleThing = context.getSimple() 

    fun doSomeVoodoo() { 
     val text : String = context.getString() 
    } 
} 

Sử dụng lateinit modifier khi bạn không thể khởi tạo giá trị trong quá trình thi, nhưng bạn chắc chắn nó sẽ được thực hiện trước khi truy cập đọc đầu tiên của bạn. này là phổ biến khi một dependency injection, IoC container, hoặc một cái gì đó tạo ra một phiên bản trống của lớp học của bạn và sau đó khởi nó ngay lập tức:

class TestClass() { 
    private lateinit var context : Context // set by something else after construction 

    fun doSomeVoodoo() { 
     val text : String = context.getString() 
    } 
} 

Đối lateinit tài sản phải hiện là một var và không làm việc với nguyên thủy loại.

Bạn cũng có thể khai báo thuộc tính var và không khởi tạo nó nếu bạn sử dụng một đại biểu được thiết kế cho mục đích đó, chẳng hạn như Delegates.notNull().này tương tự như lateinit và phổ biến khi bạn muốn có một var mà không có trạng thái ban đầu, nhưng được thiết lập sau đó sau khi xây dựng tại chưa biết thời điểm nào:

public class TestClass() { 
    private var context: Context by Delegates.notNull() 

    public fun doSomeVoodoo() { 
     // if context is not set before this is called, an exception is thrown 
     val text : String = context.getString() 
    } 
} 
Các vấn đề liên quan