স্কালাল বৈশিষ্ট্যে কখন ভাল বা ডিফ ব্যবহার করবেন?


90

আমি কার্যকর স্কালা স্লাইডগুলির মধ্য দিয়ে যাচ্ছিলাম এবং এটি অ্যাবস্ট্রাক্ট সদস্যদের জন্য কখনও ব্যবহার valনা traitকরে এর defপরিবর্তে 10 স্লাইডে উল্লেখ করেছে । স্লাইড বিস্তারিতভাবে উল্লেখ না কেন বিমূর্ত ব্যবহার valএকটি traitবিরোধী প্যাটার্ন। যদি কেউ বিমূর্ত পদ্ধতিগুলির জন্য একটি বৈশিষ্ট্যে ভাল বনাম ডিএফ ব্যবহারের চারপাশে সেরা অনুশীলনের ব্যাখ্যা দিতে পারে তবে আমি এটির প্রশংসা করব

উত্তর:


130

এ , ক , ক বা এ defদুটির মাধ্যমে প্রয়োগ করা যেতে পারে । সুতরাং এটি কোনও সদস্যকে সংজ্ঞায়নের সবচেয়ে বিমূর্ত রূপ। যেহেতু বৈশিষ্ট্যগুলি সাধারণত বিমূর্ত ইন্টারফেস হয়, আপনি যে চান তা বলছে বাস্তবায়নটি কীভাবে করা উচিত। আপনি যদি এর জন্য জিজ্ঞাসা করেন তবে একটি বাস্তবায়নকারী শ্রেণী একটি ব্যবহার করতে পারে না ।defvallazy valobjectvalvaldef

valআপনার যদি কেবল স্থিতিশীল শনাক্তকারী প্রয়োজন, তবে পথ-নির্ভর ধরণের জন্য প্রয়োজন হয় A এটি এমন কিছু যা আপনার সাধারণত প্রয়োজন হয় না।


তুলনা করা:

trait Foo { def bar: Int }

object F1 extends Foo { def bar = util.Random.nextInt(33) } // ok

class F2(val bar: Int) extends Foo // ok

object F3 extends Foo {
  lazy val bar = { // ok
    Thread.sleep(5000)  // really heavy number crunching
    42
  }
}

তোমার যদি থাকত

trait Foo { val bar: Int }

আপনি সংজ্ঞায়িত করতে পারবেন না F1বা F3


ঠিক আছে, এবং আপনাকে বিভ্রান্ত করার জন্য এবং @ ওম-নাম-নাম-উত্তর ab বিমূর্ত ব্যবহার করে valসূচনা সমস্যার কারণ হতে পারে:

trait Foo { 
  val bar: Int 
  val schoko = bar + bar
}

object Fail extends Foo {
  val bar = 33
}

Fail.schoko  // zero!!

এটি একটি কুরুচিপূর্ণ সমস্যা যা আমার ব্যক্তিগত মতামত অনুসারে ভবিষ্যতে স্কেলার সংস্করণগুলিতে সংকলকটিতে এটি ঠিক করে দূরে চলে যাওয়া উচিত, তবে হ্যাঁ, বর্তমানে এটিও একটি কারণ যার কারণে বিমূর্তটি ব্যবহার করা উচিত নয় val

সম্পাদনা (জানুয়ারী ২০১)): আপনাকে valএকটি lazy valবাস্তবায়ন সহ একটি বিমূর্ত ঘোষণাকে ওভাররাইড করার অনুমতি দেওয়া হয় , যাতে এটি আরম্ভের ব্যর্থতাও রোধ করে।


8
কৃপণ আরম্ভের আদেশ এবং আশ্চর্যজনক শূন্যতার কথা?
সর্বনাম-মনোনীত

হ্যাঁ ... আমি সেখানে যেতে চাই না। সত্য এগুলিও ভাল এর বিরুদ্ধে যুক্তি, তবে আমি মনে করি যে মূল প্রেরণাটি কেবল বাস্তবায়ন আড়াল করা উচিত।
0__

4
এটি সাম্প্রতিক স্কালার সংস্করণে পরিবর্তিত হতে পারে (এই মন্তব্য হিসাবে 2.11.4), তবে আপনি একটি valদিয়ে একটি ওভাররাইড করতে পারেন lazy val। তোমার কথন আপনার তৈরি করতে সক্ষম নাও হতে হবে F3যদি barছিল valসঠিক নয়। তাই বলা হয়, বৈশিষ্ট্যগুলো মধ্যে বিমূর্ত সদস্যদের সবসময় হওয়া উচিত def'র
mplis

যদি আপনি প্রতিস্থাপন val schoko = bar + barকরেন তবে ফু / ফেল উদাহরণটি প্রত্যাশার মতো কাজ করে lazy val schoko = bar + bar। এটি সূচনা আদেশের উপর কিছুটা নিয়ন্ত্রণের একটি উপায়। এছাড়াও, lazy valপরিবর্তিত defক্লাসের পরিবর্তে ব্যবহার করা পুনরবৃত্তিকে এড়িয়ে চলে।
অ্যাড্রিয়ান

4
যদি আপনি পরিবর্তন val bar: Intকরতে def bar: Int Fail.schokoএখনো শূন্য।
জ্যাস্পার-এম

8

আমি valবৈশিষ্ট্যগুলিতে ব্যবহার করতে পছন্দ করি না কারণ ভাল ঘোষণার সূচনাটি অস্পষ্ট এবং প্রারম্ভিককরণের স্বজ্ঞাত নয় has আপনি ইতিমধ্যে শ্রেণিবিন্যাসের কাজ করতে একটি বৈশিষ্ট্য যুক্ত করতে পারেন এবং এটি আগে কাজ করা সমস্ত জিনিসকে ভেঙে ফেলবে, আমার বিষয় দেখুন: কেন চূড়ান্ত ক্লাসে প্লেইন ভ্যাল ব্যবহার করা হচ্ছে?

এই ভাল ঘোষণাটি আপনার ব্যবহারের সমস্ত বিষয় মাথায় রাখা উচিত যা শেষ পর্যন্ত আপনাকে একটি ত্রুটির দিকে নিয়ে যায়।


আরও জটিল উদাহরণ সহ আপডেট করুন

তবে এমন অনেক সময় রয়েছে যখন আপনি ব্যবহার এড়াতে পারবেন না val। @ 0__ হিসাবে কখনও কখনও উল্লেখ করা হয়েছে যে আপনার একটি স্থিতিশীল শনাক্তকারী প্রয়োজন এবং defএটি একটি নয়।

তিনি কী সম্পর্কে কথা বলছিলেন তা দেখানোর জন্য আমি একটি উদাহরণ সরবরাহ করব:

trait Holder {
  type Inner
  val init : Inner
}
class Access(val holder : Holder) {
  val access : holder.Inner =
    holder.init
}
trait Access2 {
  def holder : Holder
  def access : holder.Inner =
    holder.init
}

এই কোড ত্রুটি উত্পাদন করে:

 StableIdentifier.scala:14: error: stable identifier required, but Access2.this.holder found.
    def access : holder.Inner =

আপনি যদি এক মিনিট সময় নিয়ে ভাবেন তবে আপনি বুঝতে পারবেন যে সংকলকটির অভিযোগ করার কারণ রয়েছে। ইন Access2.accessকেস এটা কোনো উপায়ে আহরণ রিটার্ন টাইপ না। def holderএর অর্থ এটি ব্যাপকভাবে কার্যকর করা যেতে পারে। এটি প্রতিটি কলের জন্য পৃথক ধারককে ফিরিয়ে দিতে পারে এবং ধারকরা বিভিন্ন Innerধরণের অন্তর্ভুক্ত করবে । তবে জাভা ভার্চুয়াল মেশিনটি একই ধরণের প্রত্যাবর্তন প্রত্যাশা করে।


4
প্রারম্ভিক ক্রমটি অর্ডার করা উচিত নয়, তবে পরিবর্তে আমরা রানটাইমের সময় এনপিই'র বিস্ময়কর হয়ে উঠি vis
জোনাথন নিউফিল্ড

স্কালার মধ্যে ডিক্যারেটিভ সিনট্যাক্স রয়েছে যা পিছনে আবশ্যকীয় প্রকৃতিকে আড়াল করে। কখনও কখনও সেই
অনিচ্ছাকৃততা

-4

সর্বদা ডিএফ ব্যবহার করা কিছুটা বিশ্রী বলে মনে হয় যেহেতু এরকম কিছু কাজ করবে না:

trait Entity { def id:Int}

object Table { 
  def create(e:Entity) = {e.id = 1 }  
}

আপনি নিম্নলিখিত ত্রুটি পাবেন:

error: value id_= is not a member of Entity

4
কোন প্রাসঙ্গিক। আপনি যদি ডিএফ (ত্রুটি: ভালকে পুনরায় নিযুক্তকরণ) এর পরিবর্তে ভাল ব্যবহার করেন তবে আপনার ত্রুটিও রয়েছে এবং এটি পুরোপুরি যৌক্তিক।
volia17

আপনি যদি ব্যবহার না var। মুল বক্তব্যটি হ'ল যদি তারা ক্ষেত্র হয় তবে তাদের এগুলি হিসাবে মনোনীত করা উচিত। আমি কেবল মনে করি সবকিছু যেমন defসংক্ষিপ্ত দৃষ্টিশক্তি হিসাবে রয়েছে।
দিমিত্রি

@ ডিমিট্রি, নিশ্চিত, ব্যবহার করে varআপনাকে এনকেপসুলেশন ভেঙে দিন। তবে একটি def(বা ক val) ব্যবহার বৈশ্বিক চলকের চেয়ে বেশি পছন্দ করা হয়। আমি মনে করি আপনি যা সন্ধান করছেন এটি এমন কিছু case class ConcreteEntity(override val id: Int) extends Entityযা আপনি এটি থেকে তৈরি করতে পারেন এটি def create(e: Entity) = ConcreteEntity(1)এনক্যাপসুলেশন ভেঙে দেওয়া এবং কোনও শ্রেণিটিকে সত্তা পরিবর্তন করার অনুমতি দেওয়ার চেয়ে নিরাপদ।
জোনো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.