見えないAttribute

2505 ワード

オブジェクト向けのプログラミング言語には、本当の属性ではなく、「読む」「書く」という特殊な属性を定義することができますが、実際には特定の方法を呼び出しています.ここでは、「クラス」ベースのPythonと、「プロトタイプチェーン」ベースのJavascriptの2つの代表的なプログラミング言語を使用します.
Javascriptの例
Javascriptのキーワードgetsetは少ないですが、ルールは直感的です.簡単に言えば、通常の関数定義の前に、getまたはsetを追加します.
この文法を具体的に説明するには、Javascriptの奇妙な方法で文法を定義する方法を説明しなければなりません.この文章を参考にしてください.この文章は使い方だけを述べる.
var a = {
  set blah(v) { console.log(`your argument is ${v}`) },
  get blah() { return '<<>>' }
}
blahという属性を直接定義していませんが、今は使用できます.
a.blah
//> "<<>>"
a.blah = 3
//  your argument is 3
//> 3

それ以外にも、Object.definePropertyは同じことをすることができます.
var a = {}

Object.defineProperty(a, 'blah', {
  set: (v) => console.log(`your argument is ${v}`),
  get: () => '<<>>'
})
a.blah
//> "<<>>"
a.blah = 3
//  your argument is 3 
//> 3

Pythonの例
Pythonでは、@property@varname.setterがこのことをするために使われています.
class MyClass:
  def __init__(self):
    self._val = 3

  @property
  def val(self):
    print("from @property, _val = ", self._val)

  @val.setter
  def val(self, val):
    print("from @val.setter")
    self._val = val

実行してください
myobj = MyClass()
myobj.val
#> from @property, _val =  3
myobj.val = 4
#> from @val.setter
myobj.val
#> from @property, _val =  4
myobj._val
#> 4

JSのgetsetの表現と同様に,存在しない属性valにアクセスしている.
このほか、Pythonの「descriptor」でも似たようなことができます.
class MyDescriptor:
  def __get__(self, obj, owner):
    print("from MyDescriptor.__get__, val = ", obj.val)
  def __set__(self, obj, val):
    print("from MyDescriptor.__set__")
    obj.val = val

次は「descriptor」が使えます.
class MyClass:
  desc = MyDescriptor()
  def __init__(self):
    self.val = 3

このクラスのdesc属性は、Javascriptのgetsetと同じ動作を示します.
myobj = MyClass()
myobj.desc
#> from MyDescriptor.__get__, val =  3
myobj.desc = 4
#> from MyDescriptor.__set__
myobj.desc
#> from MyDescriptor.__get__, val =  4
myobj.val
#> 4

原文:http://madmuggle.me/articles/FakeAttribute.html