শিশু শ্রেণীর জন্য কোটলিন ভেরিয়েবল সূচনা মান 0 সহ ভেরিয়েবল সূচনা করার জন্য অদ্ভুত আচরণ করে


16

আমি নিম্নলিখিত শ্রেণীর শ্রেণিবিন্যাস তৈরি করেছি:

open class A {
    init {
        f()
    }

    open fun f() {
        println("In A f")
    }
}

class B : A() {
    var x: Int = 33

    init {
        println("x: " + x)
    }

    override fun f() {
        x = 1
        println("x in f: "+ x)
    }

    init {
        println("x2: " + x)
    }
}

fun main() {
    println("Hello World!!")
    val b = B()
    println("in main x : " + b.x)
}

এই কোড আউটপুট হয়

Hello World!!
x in f: 1
x: 33
x2: 33
in main x : 33

কিন্তু যদি আমি আরম্ভের পরিবর্তন xথেকে

var x: Int = 33

প্রতি

var x: Int = 0

আউটপুট উপরের আউটপুটটির বিপরীতে পদ্ধতির প্রার্থনা দেখায়:

Hello World!!
x in f: 1
x: 1
x2: 1
in main x : 1

কেউ কি জানেন যে কেন সূচনাটি 0অন্য মান সহকারীর চেয়ে আলাদা আচরণের কারণ হয়?


4
সরাসরি সম্পর্কিত নয়, তবে কন্সট্রাক্টরদের কাছ থেকে ওভাররিডেবল পদ্ধতিগুলি কল করা সাধারণত একটি ভাল অনুশীলন নয় কারণ এটি অপ্রত্যাশিত আচরণের কারণ হতে পারে (এবং কার্যকরভাবে সুপারক্লাস চুক্তি / উপক্লাস থেকে আক্রমণকারীদের ভঙ্গ করা)।
আদম হোয়েক

উত্তর:


18

সুপার ক্লাস সাব ক্লাসের আগে আরম্ভ করা হয়।

বি এর কনস্ট্রাক্টর কলটি কনট্রাক্টরকে কল করে, যা ফাংশনটি এফ প্রিন্টিংকে "এক্স ইন ফ: 1" বলে, এ আরম্ভ করার পরে, বাকী বিয়ের আরম্ভ করা হয়।

সুতরাং মূলত, মানটির সেটিংটি ওভাররাইট করা হচ্ছে।

(আপনি যখন কোটলিনে আদিমদের শূন্য মানের সাথে আরম্ভ করবেন তখন তারা প্রযুক্তিগতভাবে কেবল আরম্ভ করবেন না)

আপনি "স্বাক্ষর" আচরণটি স্বাক্ষর থেকে পরিবর্তন করে পর্যবেক্ষণ করতে পারেন

var x: Int = 0 প্রতি var x: Int? = 0

যেহেতু xআর আদিম নয় int, ক্ষেত্রটি আসলে একটি মানের সাথে আরম্ভ হয়, আউটপুট উত্পাদন করে:

Hello World!!
x in f: 1
x: 0
x2: 0
in main x : 0

5
আপনি যখন কোটলিনে তাদের শূন্য মানের সাথে আদিমদের সূচনা করেন তখন তারা প্রযুক্তিগতভাবে কেবলমাত্র আরম্ভ করতে চান না যা আমি পড়তে চেয়েছিলাম ... ধন্যবাদ!
দেহর

এটি এখনও একটি বাগ / অসঙ্গতি বলে মনে হচ্ছে।
ক্রপ্পেব

2
@ ক্রপপেব এটি কেবল জাভা, একা জাভা কোডেও একই আচরণ লক্ষ্য করা যায়।
কোটলিনের

8

এই আচরণটি ডকুমেন্টেশনে বর্ণিত হয়েছে - https://kotlinlang.org/docs/references/classes.html#derived-class-initialization-order

যদি এই বৈশিষ্ট্যগুলির মধ্যে কোনওটি বেস শ্রেণীর সূচনা যুক্তিতে ব্যবহৃত হয় (প্রত্যক্ষ বা অপ্রত্যক্ষভাবে, অন্য কোনও ওভাররাইড ওপেন সদস্য প্রয়োগের মাধ্যমে), এটি ভুল আচরণ বা রানটাইম ব্যর্থতার দিকে নিয়ে যেতে পারে। বেস ক্লাস ডিজাইন করার সময় আপনার কনস্ট্রাক্টর, প্রপার্টি ইনিশিয়েলজার এবং ইন ডি ব্লকে ওপেন সদস্য ব্যবহার করা উচিত নয় avoid

UPD:

একটি ত্রুটি রয়েছে যা এই অসঙ্গতি তৈরি করে - https://youtrack.jetbrains.com/issue/KT-15642

যখন কোনও সম্পত্তি সুপার কনস্ট্রাক্টরের অভ্যন্তরে ভার্চুয়াল ফাংশন কলের পার্শ্ব-প্রতিক্রিয়া হিসাবে নির্ধারিত হয়, তবে আরম্ভকারী সংজ্ঞাটি যদি টাইপ ডিফল্ট মান (নাল, আদিম শূন্য) হয় তবে তার আরম্ভকারীটি সম্পত্তিটি ওভাররাইট করে না।


1
তদ্ব্যতীত, ইন্টেলিজ আপনাকে এটি সম্পর্কে সতর্ক করে। কলিং f()মধ্যে initব্লক Aসাবধানবাণী "কল করা হচ্ছে কন্সট্রাকটর অ চূড়ান্ত ফাংশন f" দেয়
Kroppeb

আপনি যে ডকুমেন্টেশন সরবরাহ করেছেন তাতে এটি বলেছে যে "বেস ক্লাসের সূচনাটি প্রথম পদক্ষেপ হিসাবে সম্পন্ন হয় এবং ডেরিটেড শ্রেণীর সূচনা যুক্তি চালানোর আগে এটি ঘটে" যা প্রশ্নের প্রথম উদাহরণে হুবহু ঘটে। তবে দ্বিতীয় উদাহরণে var x: Int = 0উদ্ভূত শ্রেণীর সূচনা নির্দেশ ( ) চালানো হয় না যা ডকুমেন্টেশন যা বলে তার বিপরীত যা আমাকে বিশ্বাস করতে পরিচালিত করে যে এটি কোনও ত্রুটি হতে পারে।
সুবারু তাশিরো

@ সুবারুতাশিরো হ্যাঁ, আপনি ঠিক বলেছেন। এটি আরেকটি সমস্যা - youtrack.jetbrains.com/issue/KT-15642
ভ্যানোওচেক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.