কফিস্ক্রিপ্টে ব্যক্তিগত সদস্যরা?


84

কেউ কি কফিস্ক্রিপ্টে ব্যক্তিগত, অ স্থিতিশীল সদস্য তৈরি করতে জানেন? বর্তমানে আমি এটি করছি, যা ক্লাসের বাইরে ব্যবহার করা উচিত নয় তা স্পষ্ট করতে একটি আন্ডারস্কোর দিয়ে শুরু করে একটি সর্বজনীন পরিবর্তনশীল ব্যবহার করে:

class Thing extends EventEmitter
  constructor: (@_name) ->

  getName: -> @_name

শ্রেণিতে ভেরিয়েবল স্থাপন করা এটি একটি স্থির সদস্য করে তোলে, তবে আমি কীভাবে এটি অ স্থির করতে পারি? "অভিনব" না পেয়ে কি এটিও সম্ভব?

উত্তর:


20

"অভিনব" না পেয়ে কি এটিও সম্ভব?

দুঃখের বিষয়, আপনাকে অভিনব হতে হবে ।

class Thing extends EventEmitter
  constructor: (name) ->
    @getName = -> name

মনে রাখবেন, "এটি কেবল জাভাস্ক্রিপ্ট।"


4
... এবং তাই আপনাকে এটি জেএস-তে যেমন করতে হবে তেমন করতে হবে। যখন এটি সমস্ত চিনির আড়ালে লুকিয়ে রাখা সহজ, ধন্যবাদ!
thejh

4
এটা কি আসলেই ব্যক্তিগত? আপনি এখনও এটি ক্লাসের বাইরে অ্যাক্সেস করতে পারেন। a = থিং ('a') তারপরে a.getName () মান দেয় এবং a.getName = -> 'বি' সেট করে।
আমির

4
@ আমির: nameকেবল কনস্ট্রাক্টর বন্ধের ভিতরে থেকেই দৃশ্যমান। এই গিস্টটি দেখুন
thejh

13
এছাড়াও লক্ষণীয় যে @getName = -> nameএটি getNameফাংশনের কোনও সম্ভাব্য উত্তরাধিকার ভঙ্গ করে।
কেন্ডাল হপকিনস

12
এই উত্তরটি ভুল: এখানে, getNameসর্বজনীন, এবং nameকেবলমাত্র নির্মাণকারী ফাংশন থেকে অ্যাক্সেসযোগ্য তাই এটি বস্তুর কাছে সত্যই "ব্যক্তিগত" নয়।
তোথামারিও

203

ক্লাসগুলি কেবল ফাংশন তাই তারা স্কোপ তৈরি করে। এই সুযোগের ভিতরে সংজ্ঞায়িত সমস্ত কিছুই বাইরে থেকে দৃশ্যমান হবে না।

class Foo
  # this will be our private method. it is invisible
  # outside of the current scope
  foo = -> "foo"

  # this will be our public method.
  # note that it is defined with ':' and not '='
  # '=' creates a *local* variable
  # : adds a property to the class prototype
  bar: -> foo()

c = new Foo

# this will return "foo"
c.bar()

# this will crash
c.foo

কফিসক্রিপ্ট এটিকে নিম্নলিখিতগুলির মধ্যে সংকলন করে:

(function() {
  var Foo, c;

  Foo = (function() {
    var foo;

    function Foo() {}

    foo = function() {
      return "foo";
    };

    Foo.prototype.bar = function() {
      return foo();
    };

    return Foo;

  })();

  c = new Foo;

  c.bar();

  c.foo();

}).call(this);

9
এটি লক্ষ করা উচিত যে এই ব্যক্তিগত ভেরিয়েবলগুলি সাবক্লাসে উপলভ্য নয়
সিয়াসার বাউটিস্তা

45
এটিও লক্ষ করা উচিত যে 'বেসরকারী' পদ্ধতিগুলি ফাংশনের নজির হওয়ার foo.call(this)জন্য যেমনটি বলা প্রয়োজন this। এ কারণেই জাভাস্ক্রিপ্টে শাস্ত্রীয় উত্তরাধিকার অনুকরণ করার চেষ্টা করা লোমশ হয়ে যায়।
জন উইংফিল্ড

4
আরেকটি নেতিবাচকতা হ'ল ইউনিট পরীক্ষার জন্য আপনার "ব্যক্তিগত" পদ্ধতিতে অ্যাক্সেস থাকবে না
nuc

16
@ নিউক বেসরকারী পদ্ধতিগুলি এমন বাস্তবায়ন বিশদ যা তাদের যে সকল পাবলিক পদ্ধতি তাদের কল করে তাদের মাধ্যমে পরীক্ষা করা হয়, যার অর্থ হল যে ব্যক্তিগত পদ্ধতিগুলি ইউনিট পরীক্ষা করা উচিত নয়। কোনও ব্যক্তিগত পদ্ধতি যদি মনে হয় এটি ইউনিট পরীক্ষামূলক হওয়া উচিত, তবে সম্ভবত এটি একটি সর্বজনীন পদ্ধতি হওয়া উচিত। পাশাপাশি একটি ভাল ব্যাখ্যা জন্য এই পোস্ট দেখতে stackoverflow.com/questions/5750279/...
mkelley33

4
এটিও লক্ষ করা উচিত যে উপরে আপনার "ব্যক্তিগত" ভেরিয়েবলগুলি যেখানে "পাবলিক" ফাংশনে ব্যবহৃত হয় তা আপনাকে সংজ্ঞায়িত করতে হবে। অন্যথায়, কফিস্ক্রিপ্ট বিভ্রান্ত হয়ে পড়বে এবং নতুন অভ্যন্তরীণ varঘোষণাগুলি তৈরি করবে যা তাদের ছায়া দেবে।
অ্যান্ড্রু মাইনার

11

আমি এমনকি কিছু fancier দেখাতে চাই

class Thing extends EventEmitter
  constructor: ( nm) ->
    _name = nm
    Object.defineProperty @, 'name',
      get: ->
        _name
      set: (val) ->
        _name = val
      enumerable: true
      configurable: true

এখন আপনি করতে পারেন

t = new Thing( 'Dropin')
#  members can be accessed like properties with the protection from getter/setter functions!
t.name = 'Dragout'  
console.log t.name
# no way to access the private member
console.log t._name

2

ভাইটালির উত্তরের সাথে একটি সমস্যা আছে এবং তা হ'ল আপনি এমন পরিবর্তনগুলি সংজ্ঞায়িত করতে পারবেন না যে আপনি সুযোগের স্বতন্ত্র হয়ে উঠতে চান , আপনি যদি সেইভাবে একটি ব্যক্তিগত নাম তৈরি করেন এবং পরে এটি পরিবর্তন করেন তবে শ্রেণীর প্রতিটি দৃষ্টান্তের জন্য নামের মান পরিবর্তন হবে, সুতরাং একটি উপায় আছে যা আমরা এই সমস্যাটি সমাধান করতে পারি

# create a function that will pretend to be our class 
MyClass = ->

    # this has created a new scope 
    # define our private varibles
    names = ['joe', 'jerry']

    # the names array will be different for every single instance of the class
    # so that solves our problem

    # define our REAL class
    class InnerMyClass 

        # test function 
        getNames: ->
            return names;

    # return new instance of our class 
    new InnerMyClass

আপনি যদি না ব্যবহার করেন তবে বাইরে থেকে নামগুলি অ্যারে অ্যাক্সেস করা অসম্ভব নয় getNames

এটি পরীক্ষা করে দেখুন

test = new MyClass;

tempNames = test.getNames()

tempNames # is ['joe', 'jerry']

# add a new value 
tempNames.push 'john'

# now get the names again 
newNames = test.getNames();

# the value of newNames is now 
['joe', 'jerry', 'john']

# now to check a new instance has a new clean names array 
newInstance = new MyClass
newInstance.getNames() # === ['joe', 'jerry']


# test should not be affected
test.getNames() # === ['joe', 'jerry', 'john']

সংকলন জাভাস্ক্রিপ্ট

var MyClass;

MyClass = function() {
  var names;
  names = ['joe', 'jerry'];
  MyClass = (function() {

    MyClass.name = 'MyClass';

    function MyClass() {}

    MyClass.prototype.getNames = function() {
      return names;
    };

    return MyClass;

  })();
  return new MyClass;
};

আমি এই বাস্তবায়ন পছন্দ। কোন ত্রুটি?
এরিক 573

2

এখানে এমন একটি সমাধান যা এখানে অন্যান্য বেশ কয়েকটি উত্তরের সাথে https://stackoverflow.com/a/7579956/1484513 এ আঁকতে পারে । এটি একটি প্রাইভেট ক্লাস (স্থিতিশীল) অ্যারেতে প্রাইভেট ইনস্ট্যান্স (অ স্থিতিশীল) ভেরিয়েবলগুলি সঞ্চয় করে এবং সেই অ্যারের কোন উপাদানটিতে প্রতিটি উদাহরণের অন্তর্ভুক্ত ডেটা থাকে তা জানতে আইটেম আইডি ব্যবহার করে।

# Add IDs to classes.
(->
  i = 1
  Object.defineProperty Object.prototype, "__id", { writable:true }
  Object.defineProperty Object.prototype, "_id", { get: -> @__id ?= i++ }
)()

class MyClass
  # Private attribute storage.
  __ = []

  # Private class (static) variables.
  _a = null
  _b = null

  # Public instance attributes.
  c: null

  # Private functions.
  _getA = -> a

  # Public methods.
  getB: -> _b
  getD: -> __[@._id].d

  constructor: (a,b,@c,d) ->
    _a = a
    _b = b

    # Private instance attributes.
    __[@._id] = {d:d}

# Test

test1 = new MyClass 's', 't', 'u', 'v'
console.log 'test1', test1.getB(), test1.c, test1.getD()  # test1 t u v

test2 = new MyClass 'W', 'X', 'Y', 'Z'
console.log 'test2', test2.getB(), test2.c, test2.getD()  # test2 X Y Z

console.log 'test1', test1.getB(), test1.c, test1.getD()  # test1 X u v

console.log test1.a         # undefined
console.log test1._a        # undefined

# Test sub-classes.

class AnotherClass extends MyClass

test1 = new AnotherClass 's', 't', 'u', 'v'
console.log 'test1', test1.getB(), test1.c, test1.getD()  # test1 t u v

test2 = new AnotherClass 'W', 'X', 'Y', 'Z'
console.log 'test2', test2.getB(), test2.c, test2.getD()  # test2 X Y Z

console.log 'test1', test1.getB(), test1.c, test1.getD()  # test1 X u v

console.log test1.a         # undefined
console.log test1._a        # undefined
console.log test1.getA()    # fatal error

2

এখানে সেরা নিবন্ধ আমি সেটিং সম্পর্কে পাওয়া public static members, private static members, public and private members, এবং কিছু অন্যান্য সম্পর্কিত স্টাফ। এটি অনেক বিশদ এবং jsবনাম coffeeতুলনা কভার করে । এবং historical তিহাসিক কারণে এটি থেকে সেরা কোড উদাহরণ এখানে:

# CoffeeScript

class Square

    # private static variable
    counter = 0

    # private static method
    countInstance = ->
        counter++; return

    # public static method
    @instanceCount = ->
        counter

    constructor: (side) ->

        countInstance()

        # side is already a private variable, 
        # we define a private variable `self` to avoid evil `this`

        self = this

        # private method
        logChange = ->
            console.log "Side is set to #{side}"

        # public methods
        self.setSide = (v) ->
            side = v
            logChange()

        self.area = ->
            side * side

s1 = new Square(2)
console.log s1.area()   # output 4

s2 = new Square(3)
console.log s2.area()   # output 9

s2.setSide 4            # output Side is set to 4
console.log s2.area()   # output 16

console.log Square.instanceCount() # output 2

1

এখানে আপনি কীভাবে কফিস্ক্রিপ্টে ব্যক্তিগত, অ স্থির সদস্যদের ঘোষণা করতে পারেন
সম্পূর্ণ রেফারেন্সের জন্য, আপনি https://github.com/vhmh2005/jsClass এ একবার দেখে নিতে পারেন

class Class

  # private members
  # note: '=' is used to define private members
  # naming convention for private members is _camelCase

  _privateProperty = 0

  _privateMethod = (value) ->        
    _privateProperty = value
    return

  # example of _privateProperty set up in class constructor
  constructor: (privateProperty, @publicProperty) ->
    _privateProperty = privateProperty

1

কফি স্ক্রিপ্টগুলিতে "শ্রেণি" একটি প্রোটোটাইপ ভিত্তিক ফলাফলের দিকে নিয়ে যায়। সুতরাং আপনি যদি কোনও ব্যক্তিগত ভেরিয়েবল ব্যবহার করেন তবে এটি উদাহরণগুলির মধ্যে ভাগ করা হয়। তুমি এটি করতে পারো:

EventEmitter = ->
  privateName = ""

  setName: (name) -> privateName = name
  getName: -> privateName

.. দিকে

emitter1 = new EventEmitter()
emitter1.setName 'Name1'

emitter2 = new EventEmitter()
emitter2.setName 'Name2'

console.log emitter1.getName() # 'Name1'
console.log emitter2.getName() # 'Name2'

তবে ব্যক্তিগত সদস্যদের পাবলিক ফাংশনগুলির আগে রাখার বিষয়ে সতর্কতা অবলম্বন করুন, কারণ কফি স্ক্রিপ্ট পাবলিক ফাংশনগুলিকে অবজেক্ট হিসাবে ফিরিয়ে দেয়। সংকলিত জাভাস্ক্রিপ্ট দেখুন:

EventEmitter = function() {
  var privateName = "";

  return {
    setName: function(name) {
      return privateName = name;
    },
    getName: function() {
      return privateName;
    }
  };
};

0

যেহেতু কফি স্ক্রিপ্টটি জাভাস্ক্রিপ্টে সংকলন করে কেবলমাত্র আপনার ব্যক্তিগত ভেরিয়েবল থাকতে পারে তা হল ক্লোজার through

class Animal
  foo = 2 # declare it inside the class so all prototypes share it through closure
  constructor: (value) ->
      foo = value

  test: (meters) ->
    alert foo

e = new Animal(5);
e.test() # 5

এটি নিম্নলিখিত জাভাস্ক্রিপ্টের মাধ্যমে সংকলন করবে:

var Animal, e;
Animal = (function() {
  var foo; // closured by test and the constructor
  foo = 2;
  function Animal(value) {
    foo = value;
  }
  Animal.prototype.test = function(meters) {
    return alert(foo);
  };
  return Animal;
})();

e = new Animal(5);
e.test(); // 5

অবশ্যই ক্লোজার ব্যবহারের মাধ্যমে আপনার যে সমস্ত অন্যান্য ব্যক্তিগত ভেরিয়েবলগুলি থাকতে পারে তার সমান সীমাবদ্ধতা রয়েছে, উদাহরণস্বরূপ, নতুন যুক্ত পদ্ধতিগুলিতে সেগুলিতে অ্যাক্সেস নেই কারণ সেগুলি একই স্কোপে সংজ্ঞায়িত করা হয়নি।


9
এটি এক ধরণের স্থায়ী সদস্য। e = new Animal(5);f = new Animal(1);e.test()সতর্কতা এক, আমি পাঁচ চাই।
thejh

@ ওহে, দুঃখিত, তবে এখন আমি ত্রুটিটি দেখছি, অনুমান করুন যে গতকাল এই জিনিসটি সম্পর্কে চিন্তা করতে খুব দেরি হয়েছিল।
আইভো ওয়েটজেল

@ তেজ আমার সাথে এটি ঘটেছে, আমি আমার উত্তরে সেই সমস্যাটি সমাধান করার চেষ্টা করেছি।
iConnor

0

আপনি কফিস্ক্রিপ্ট ক্লাসের সাহায্যে এটি সহজেই করতে পারবেন না, কারণ তারা ক্লাস তৈরির জন্য জাভাস্ক্রিপ্ট কনস্ট্রাক্টর প্যাটার্ন ব্যবহার করে।

তবে আপনি এই জাতীয় কিছু বলতে পারেন:

callMe = (f) -> f()
extend = (a, b) -> a[m] = b[m] for m of b; a

class superclass
  constructor: (@extra) ->
  method: (x) -> alert "hello world! #{x}#{@extra}"

subclass = (args...) -> extend (new superclass args...), callMe ->
  privateVar = 1

  getter: -> privateVar
  setter: (newVal) -> privateVar = newVal
  method2: (x) -> @method "#{x} foo and "

instance = subclass 'bar'
instance.setter 123
instance2 = subclass 'baz'
instance2.setter 432

instance.method2 "#{instance.getter()} <-> #{instance2.getter()} ! also, "
alert "but: #{instance.privateVar} <-> #{instance2.privateVar}"

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

মুল বক্তব্যটি হ'ল প্রতি ক্লাসটি তাত্ক্ষণিকভাবে বন্ধ হওয়ার সময় অবশ্যই তৈরি করা উচিত। খাঁটি কফিস্ক্রিপ্ট ক্লাসে সদস্যের ক্লোজারগুলি কেবল একবার তৈরি হয় - এটি যখন ক্লাস রানটাইম "টাইপ" নির্মিত হয়।


-3

আপনি যদি সর্বজনীন থেকে পৃথক ব্যক্তিগত মেমবারকে চান তবে কেবল এটিকে $ ভেরিয়েবলের মধ্যে মুড়িয়ে দিন

$:
        requirements:
              {}
        body: null
        definitions: null

আর ব্যবহার করুন @$.requirements

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.