Jump to content

Единый принцип доступа

Принцип единообразного доступа в компьютерном программировании был сформулирован Бертраном Мейером (первоначально в его книге «Объектно-ориентированное построение программного обеспечения »). В нем говорится: «Все услуги, предлагаемые модулем , должны быть доступны через единую нотацию, которая не выдает, реализуются ли они через хранилище или посредством вычислений». [1] [2] Этот принцип обычно применим к синтаксису объектно -ориентированных языков программирования . В более простой форме оно гласит, что не должно быть синтаксической разницы между работой с атрибутом , заранее вычисленным свойством или методом / запросом объекта.

В то время как большинство примеров сосредоточено на аспекте «чтения» принципа (т. е. извлечении значения), Мейер в своей ежемесячной колонке на тему «Запись» (т. е. изменение значения) этого принципа показывает, что труднее разобраться с последствиями этого принципа. языка программирования Eiffel . Официальный сайт [3]

Объяснение

[ редактировать ]

Проблема, которую решает Мейер, связана с поддержкой крупных программных проектов или библиотек программного обеспечения. Иногда при разработке или сопровождении программного обеспечения после написания большого количества кода необходимо изменить класс или объект таким образом, чтобы превратить то, что было просто доступом к атрибуту, в вызов метода. Языки программирования часто используют другой синтаксис для доступа к атрибутам и вызова метода (например, object.something против object.something()). Изменение синтаксиса в популярных языках программирования того времени потребовало бы изменения исходного кода во всех местах, где использовался атрибут. Это может потребовать изменения исходного кода во многих разных местах в очень большом объеме исходного кода. Или, что еще хуже, если изменение произошло в библиотеке объектов, используемой сотнями клиентов, каждому из этих клиентов придется найти и изменить все места, где атрибут использовался в своем собственном коде, и перекомпилировать свои программы.

Обратный путь (от метода к простому атрибуту) на самом деле не был проблемой, поскольку всегда можно просто сохранить функцию и заставить ее просто возвращать значение атрибута.

Мейер признал необходимость для разработчиков программного обеспечения писать код таким образом, чтобы минимизировать или исключить каскадные изменения в коде, возникающие в результате изменений, которые преобразуют атрибут объекта в вызов метода или наоборот. Для этого он разработал принцип единого доступа.

Многие языки программирования не поддерживают UAP строго, но поддерживают его формы. Свойства, предоставляемые во многих языках программирования, по-другому решают проблему, которую Мейер решал с помощью своего UAP. Вместо предоставления единой унифицированной записи свойства предоставляют способ вызова метода объекта, используя ту же нотацию, которая используется для доступа к атрибутам. Отдельный синтаксис вызова метода по-прежнему доступен.

Пример UAP

[ редактировать ]

Если язык использует синтаксис вызова метода, это может выглядеть примерно так.

// Assume print displays the variable passed to it, with or without parens
// Set Foo's attribute 'bar' to  value 5.
Foo.bar(5)
print Foo.bar()

При выполнении должно отображаться:

5

Будь или нет Foo.bar(5) вызывает функцию или просто устанавливает атрибут, скрытый от вызывающего объекта. Аналогично ли Foo.bar() просто получает значение атрибута или вызывает функцию для вычисления возвращаемого значения — это деталь реализации, скрытая от вызывающей стороны.

Если язык использует синтаксис атрибутов, синтаксис может выглядеть следующим образом.

Foo.bar = 5
print Foo.bar

Опять же, независимо от того, вызывается ли метод или просто присваивается значение атрибуту, скрыто. из вызывающего метода.

Проблемы

[ редактировать ]

Однако UAP сам по себе может привести к проблемам, если его использовать в местах, где различия между методами доступа не являются незначительными, например, когда вычисление возвращаемого значения требует больших затрат или запускает операции кэширования. [2]

Примеры языков

[ редактировать ]

Свойства Python могут использоваться для разрешения метода быть вызван с тем же синтаксисом, что и доступ к атрибуту. В то время как UAP Мейера имел бы единое обозначение как для доступа к атрибутам, так и для вызова метода (синтаксис вызова метода), язык с поддержкой свойств по-прежнему поддерживает отдельные обозначения атрибутов и доступ к методу. Свойства позволяют использовать нотацию атрибута, но скрывают тот факт, что метод вызывается, а не просто получает или устанавливает значение.

Таким образом, Python оставляет возможность соблюдения UAP на усмотрение отдельного программиста. Встроенный @property Функция обеспечивает простой способ оформления любого данного метода в синтаксисе доступа к атрибутам, тем самым абстрагируя синтаксическую разницу между вызовами методов и доступом к атрибутам. [4]

В Python у нас может быть код, который обращается к Egg объект, который можно определить так, что вес и цвет являются простыми атрибутами, как показано ниже.

"""
>>> egg = Egg(4.0, "white")
>>> egg.color = "green"
>>> print(egg)
Egg(4.0, green)
"""

class Egg:
    def __init__(self, weight, color) -> None:
        self.weight = weight
        self.color = color

    def __str__(self) -> str:
        return f"{__class__.__name__}({self.weight}, {self.color})"

Или объект Egg может использовать свойства и вместо этого вызывать методы получения и установки.

# ...(snip)...
class Egg:
    def __init__(self, weight_oz: float, color_name: float) -> None:
        self.weight = weight_oz
        self.color = color_name
        
    @property
    def color(self) -> str:
        '''Color of the Egg'''
        return to_color_str(self._color_rgb)

    @color.setter
    def color(self, color_name: str) -> None:
        self._color_rgb = to_rgb(color_name)   

    @property
    def weight(self) -> float:
        '''Weight in Ounces'''
        return self._weight_gram / 29.3

    @weight.setter
    def weight(self, weight_oz: float) -> None:
        self._weight_gram = 29.3 * weight_oz

    # ...(snip)...
Обрезанные коды следующие:
import webcolors

# class Egg:

def to_color_str(rgb: webcolors.IntegerRGB) -> str:
    try:
        return webcolors.rgb_to_name(rgb)
    except ValueError:
        return webcolors.rgb_to_hex(rgb)
    
def to_rgb(color_name: str) -> webcolors.IntegerRGB:
    try:
        return webcolors.name_to_rgb(color_name)
    except ValueError:
        return webcolors.hex_to_rgb(color_name)


if __name__ == "__main__":
    import doctest
    doctest.testmod()

Независимо от того, каким путем Egg определен, вызывающий код может остаться прежним. Осуществление Egg может переключаться из одной формы в другую, не затрагивая код, использующий класс Egg. Языки, реализующие UAP, также обладают этим свойством.

Рассмотрим следующее

y = Egg.new("Green")
y.color = "White" 
puts y.color

Теперь класс Egg можно определить следующим образом

class Egg
  attr_accessor :color
  def initialize(color)
    @color = color
  end
end

Приведенный выше начальный сегмент кода будет отлично работать, если Egg будет определен как таковой. Яйцо Класс также можно определить, как показано ниже, где цвет — это метод. Вызывающий код будет все еще работает, без изменений, если Egg определить следующим образом.

class Egg
  
  def initialize(color)
    @rgb_color = to_rgb(color)
  end

  def color
     to_color_name(@rgb_color)
  end
 
  def color=(color) 
     @rgb_color = to_rgb(color)
  end

  private
  def to_rgb(color_name)
     .....
  end

  def to_color_name(color)
     ....
  end
end

Обратите внимание, что хотя color выглядит как атрибут в одном случае и пара методов в следующем интерфейс класса остается прежним. Человек, поддерживающий класс Egg, может переключаться с одной формы на другую, не опасаясь взлома кода вызывающего объекта. Ruby следует за пересмотренным UAP, attr_accessor :color действует только как синтаксический сахар для создания методов доступа/установки для color. В Ruby нет способа получить переменную экземпляра из объекта без вызова для нее метода.

Строго говоря, Ruby не следует оригинальному UAP Мейера в том смысле, что синтаксис доступа к атрибуту отличается от синтаксиса вызова метода. Но здесь доступ к атрибуту всегда будет осуществляться через функцию, которая часто генерируется автоматически. Таким образом, по сути, любой тип доступа вызывает функцию, и язык соответствует пересмотренному принципу унифицированного доступа Мейера.

Язык C# поддерживает свойства классов , которые предоставляют средства для определения get и set операции ( геттеры и сеттеры ) для переменной-члена. Синтаксис доступа к свойству или его изменения такой же, как и для доступа к любой другой переменной-члену класса, но фактическая реализация этого может быть определена либо как простой доступ для чтения/записи, либо как функциональный код.

public class Foo
{
    private string _name;

    // Property
    public int Size
    {
        get;    // Getter
        set;    // Setter
    }

    // Property
    public string Name
    {
        get { return _name; }     // Getter
        set { _name = value; }    // Setter
    }
}

В приведенном выше примере класс Foo содержит два свойства, Size и Name. Size Свойство — это целое число, которое можно читать (получить) и записать (установить). Аналогичным образом, Name Свойство — это строка, которую также можно читать и изменять, но ее значение хранится в отдельной (частной) переменной класса. _name.

Опуская set операция в определении свойства делает свойство доступным только для чтения, опуская при этом get операция делает его доступным только для записи.

Использование свойств использует UAP, как показано в коде ниже.

    public Foo CreateFoo(int size, string name)
    {
        var foo = new Foo();
        foo.Size = size; // Property setter
        foo.Name = name; // Property setter
        return foo;
    }

В C++ нет ни UAP, ни свойств, когда объект изменяется так, что атрибут (цвет) становится парой функций ( getA, setA ). Любое место в нем использует экземпляр объекта и либо устанавливает, либо получает значение атрибута ( x = obj.color или obj.color = x) необходимо изменить для вызова одной из функций. ( x = obj.getColor() или obj.setColor(x)). Используя шаблоны и перегрузку операторов , можно подделать свойства, но это сложнее, чем в языках, которые напрямую поддерживают свойства. Это усложняет сопровождение программ на C++. Распределенные библиотеки объектов C++ должны с осторожностью относиться к тому, как они предоставляют доступ к данным-членам.

JavaScript поддерживает вычисляемые свойства с 2009 года. [5]

  1. ^ Мейер, Бертран (1997). Объектно-ориентированное построение программного обеспечения (второе изд.). Прентис Холл. п. 57. ИСБН  978-0-13-629155-8 .
  2. ^ Jump up to: а б «Принцип UniformAccess» . c2 вики . Проверено 6 августа 2013 г.
  3. ^ Мейер, Бертран. «Колонка EiffelWorld: Бизнес плюс удовольствие» . Проверено 6 августа 2013 г.
  4. ^ Официальная документация Python, встроенные функции.
  5. ^ w3schools.com, Средства доступа к Javascript
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 3b42ea43070b1d8a6fce46d2716c5ad8__1693370700
URL1:https://arc.ask3.ru/arc/aa/3b/d8/3b42ea43070b1d8a6fce46d2716c5ad8.html
Заголовок, (Title) документа по адресу, URL1:
Uniform access principle - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)