Хорошо, класс — сегодня я здесь, чтобы поговорить о различиях и сходствах, которые есть у PHP и Ruby, когда речь идет о свойствах объектов, методах и их видимости, о том, как вы создаете переменные внутри классов и как вы можете взаимодействовать с ними.
Краткий обзор того, что мы знаем
В PHP свойства объекта могут быть установлены на одно из трех значений; public
, protected
и private
. Свойства, которые не имеют декларации видимости, по умолчанию являются открытыми. Каждое из этих объявлений изменяет информацию, доступную для самого класса, его родительских и дочерних объектов и другого кода, взаимодействующего с ним. Давайте вспомним, как они работают быстро.
- Публичные переменные доступны везде
- Защищенные переменные доступны только внутри класса и его родителей или детей
- Закрытые переменные доступны только в классе, где они указаны, и недоступны для классов, которые расширяют их
Для обработки взаимодействий с защищенными и закрытыми свойствами обычно создаются методы доступа getter и setter. Это функции, которые позволяют вам устанавливать и извлекать значения свойств, и, как правило, все они выглядят примерно одинаково — если только они на самом деле не выполняют манипуляции с данными, которые хранятся, их обычно считают однострочными функциями, возвращающими или устанавливающими свойство :
<?PHP class animal { private $_species; protected $_name; public function get_species() { return $this->_species; } public function get_name() { return $this->_name; } } class pterodactyl extends animal { public function __construct() { $this->_name = $name; $this->_species = 'dinosaur'; } } $my_big_birdie = new pterodactyl('Daryl'); var_dump($my_big_birdie->get_name()); // string(5) 'Daryl' var_dump($my_big_birdie->get_species()); // NULL
Вызов метода get_name
возвращает имя, которое мы установили, поскольку эта переменная была защищена и доступна в дочернем классе. Установив _species
в дочернем классе, он создал новое открытое свойство с именем _species и оставил приватное свойство _species в родительском классе NULL. Полный дамп $my_big_birdie
покажет нам это:
Object(pterodactyl)#1 (3) { ["_species":"animal":private]=> NULL ["_name":protected]=> string(5) "Daryl" ["_species"]=> string(8) "dinosaur" }
У Ruby точно нет свойств, как мы о них думаем. Вместо этого вы должны определить методы получения и установки для любых переменных экземпляра, к которым вы хотите получить доступ. Их обычно называют читателями и писателями. (Переменные с символом @ перед ними являются переменными экземпляра, что означает, что они доступны внутри области видимости класса.)
class Animal def initialize(name) @name = name end def name @name end def name=(name) @name = name end def species @species end end
В этом примере мы реализовали класс животных из PHP в Ruby. Обратите внимание, что метод определения определяется простым добавлением равенства в конец имени метода.
Поскольку написание методов получения и установки может быть повторяющимся процессом, Ruby упрощает это, позволяя нам объявлять переменные экземпляра, которые мы хотим использовать в качестве атрибутов:
class Animal attr_reader :species attr_accessor :name def initialize(name) @name = name end end
Теперь у нас тот же класс, что и раньше, за исключением того, что мы создаем наши attr_reader
получения и установки с помощью Ruby attr_reader
и attr_accessor
. attr_reader
создает только метод получения, attr_writer
(здесь не используется) только метод установки, а attr_accessor
создает оба метода. В 90% случаев это все, что нам нужно сделать, чтобы представить наши переменные в качестве атрибутов, и в тех случаях, когда вам требуется больше функциональности, вы можете просто использовать стандартную конструкцию метода.
В Ruby также есть разные реализации Public, Private и Protected. По умолчанию все методы являются public
, но вы можете объявить видимость, сделав один protected
или private
оператор, и тогда у всех последующих методов будет такая видимость. Это позволяет группировать методы с одинаковой видимостью:
class MyClass # the default visibility is public def my_public_method end protected def my_protected_method end def my_other_protected_method end private def my_private_method end end
Реализация защищенных и закрытых в Ruby сильно отличается от реализации в PHP и не имеет ничего общего с наследованием объектов. Private в Ruby больше похож на Protected в PHP. Закрытый метод в Ruby может быть доступен внутри контекста объекта или любого унаследованного объекта.
class Foo private def bar puts "bar called" end end class Blarg < Foo def initialize bar end end
Поскольку класс Blarg
расширяет Foo
, он может вызывать приватный метод bar.
Реализация защищенного в Ruby полностью отличается от чего-либо в PHP. Защищенные методы могут быть вызваны любым объектом того же класса:
class Person attr_writer :mother def initialize(name) @name = name end def mother_name @mother.name if end protected def name @name end end me = Person.new('Mal') mum = Person.new('Jeni') me.mother = mum puts me.mother_name # => Jeni puts me.name # => NoMethodError: protected method `name' called for #
Здесь у нас есть класс person, который разрешает защищенный доступ только к имени. Когда я создаю два экземпляра и устанавливаю атрибут mother одного экземпляра для другого экземпляра, то метод mother_name
способен вызывать атрибут name
материнской переменной, однако я не могу вызвать атрибут name
вне области действия самого объекта. ,
Это был краткий обзор некоторых фундаментальных различий между PHP и свойствами классов Ruby и видимостью методов — можете ли вы вспомнить какие-либо другие основные отличия, о которых стоит упомянуть?