Можно ли реализовать свойства на других языках, кроме C #? - PullRequest
2 голосов
/ 23 марта 2009

Во время недавней встречи с C # и WPF мне понравились свойства C #:

public double length_inches
{
    get { return length_metres * 39.0; }
    set { length_metres = value/39.0; }
}

Заметив, конечно, что length_metres может измениться с поля на свойство, и код не должен заботиться. WPF также может с радостью связывать элементы пользовательского интерфейса со свойствами объекта.

Когда я впервые узнал о классах и объектах, я предположил, что есть способ сделать это, потому что это казалось таким очевидным! Смысл сокрытия сложности внутри класса заключается в том, что вам больше не нужно заботиться о том, что хранится. Но потребовалось до сих пор, чтобы увидеть это.

Забавно, я впервые увидел, что это сделано в VB.Net. Это передний край чистоты ОО.

Вопрос в том, могу ли я воссоздать свойства на других языках, которые я использую чаще, например на javascript, python, php? В javascript, если я установлю переменную на замыкание, не получу ли я снова замыкание, а не результат?

Ответы [ 17 ]

1 голос
/ 23 марта 2009

Определенно возможно реализовать свойства на других языках. VB и F #, например, имеют явную поддержку свойств. Но оба они нацелены на CLR, которая имеет поддержку свойств.

VB.

Public Property Name As String 
  Get 
    return "someName"
  End Get
  Set
    ...
  End Set
End Property

Я не верю, что javascript или PHP поддерживают синтаксис свойств, но я не очень знаком с этими языками. Можно создать полевые методы доступа get / set практически на любом языке, который имитирует свойства.

Под капотом свойства .Net на самом деле просто приводят к получению / установке методов. У них просто очень хорошая обертка:)

0 голосов
/ 24 марта 2009

Boo - это язык .NET, очень похожий на Python, но со статической типизацией. Может реализовывать свойства:

class MyClass:
    //a field, initialized to the value 1
    regularfield as int = 1 //default access level: protected

    //a string field
    mystringfield as string = "hello"

    //a private field
    private _privatefield as int

    //a public field
    public publicfield as int = 3

    //a static field: the value is stored in one place and shared by all
    //instances of this class
    static public staticfield as int = 4

    //a property (default access level: public)
    RegularProperty as int:
        get: //getter: called when you retrieve property
            return regularfield
        set: //setter: notice the special "value" variable
            regularfield = value

    ReadOnlyProperty as int:
        get:
            return publicfield

    SetOnlyProperty as int:
        set:
            publicfield = value

    //a field with an automatically generated property
    [Property(MyAutoProperty)]
    _mypropertyfield as int = 5
0 голосов
/ 23 марта 2009

Соглашение заключается в реализации методов get_PropertyName() и set_PropertyName() (и это все, что есть в CLR. Свойства являются просто синтаксическим сахаром в VB.NET/C# - поэтому переход от поля к свойству или наоборот ломается и требует перекомпиляции клиентского кода.

public int get_SomeValue() { return someValue; }
public void set_SomeValue(int value) { someValue = value; }
private int someValue = 10;

// client
int someValue = someClass.get_SomeValue();
someClass.set_SomeValue(12);
0 голосов
/ 23 марта 2009

ActionScript 3 (javascript на стероидах) также имеет синтаксис get / set

0 голосов
/ 24 марта 2009

Когда я впервые играл с Visual Basic (например, версия 1 или что-то), первое, что я сделал, это попытался воссоздать свойства в C ++. Возможно, раньше шаблоны были доступны для меня в то время, но теперь это будет что-то вроде:

template <class TValue, class TOwner, class TKey>
class property
{
    TOwner *owner_;

public:
    property(TOwner *owner)
        : owner_(owner) {}

    TValue value() const
    {
        return owner_->get_property(TKey());
    }

    operator TValue() const
    {
        return value();
    }

    TValue operator=(const TValue &value)
    {
        owner_->set_property(TKey(), value);
        return value;
    }
};

class my_class
{
public:
    my_class()
        : first_name(this), limbs(this) {}

    struct limbs_k {};
    struct first_name_k {};

    property<std::string, my_class, first_name_k> first_name;
    property<int, my_class, limbs_k> limbs;

    std::string get_property(const first_name_k &);
    void set_property(const first_name_k &, const std::string &value);

    int get_property(const limbs_k &);
    void set_property(const limbs_k &, int value);
};

Обратите внимание, что параметр "key" игнорируется в реализациях get_property / set_property - он только там, чтобы эффективно действовать как часть имени функции через разрешение перегрузки.

Теперь пользователь my_class сможет ссылаться на открытые члены first_name и limbs во многих ситуациях, как если бы они были необработанными полями, но они просто предоставляют альтернативный синтаксис для вызова соответствующего get_property / set_property функции-члены.

Это не идеально, потому что в некоторых ситуациях вам нужно вызывать value () для свойства, чтобы получить значение, когда компилятор не может определить требуемое преобразование типа. Также вы можете получить предупреждение от передачи this членам в конструкторе, но вы можете отключить это в этом случае.

0 голосов
/ 24 марта 2009

Вы можете делать это на разных языках, с разной степенью синтаксического сахара и магии. Python, как уже упоминалось, обеспечивает поддержку для этого (и, используя декораторы, вы, безусловно, можете очистить его еще больше). PHP может предоставить разумное факсимиле с соответствующими методами __get () и __set () (возможно, с некоторой косвенностью. Если вы работаете с Perl, вы можете использовать некоторые исходные фильтры для репликации поведения. Ruby уже требует, чтобы все прошло

0 голосов
/ 24 марта 2009

Вы можете сделать что-то подобное с PHP5 магическими функциями .

class Length {
    public $metres;
    public function __get($name) {
        if ($name == 'inches')
            return $this->metres * 39;
    }
    public function __set($name, $value) {
        if ($name == 'inches')
            $this->metres = $value/39.0;
    }
}

$l = new Length;
$l->metres = 3;
echo $l->inches;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...