1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
|
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<sect1 xml:id="language.oop5.abstract" xmlns="http://docbook.org/ns/docbook">
<title>Class Abstraction</title>
<para>
PHP has abstract classes, methods, and properties.
Classes defined as abstract cannot be instantiated, and any class that
contains at least one abstract method or property must also be abstract.
Methods defined as abstract simply declare the method's signature and whether it is public or protected;
they cannot define the implementation. Properties defined as abstract
may declare a requirement for <literal>get</literal> or <literal>set</literal>
behavior, and may provide an implementation for one, but not both, operations.
</para>
<para>
When inheriting from an abstract class, all methods marked abstract in
the parent's class declaration must be defined by the child class,
and follow the usual
<link linkend="language.oop5.inheritance">inheritance</link> and
<link linkend="language.oop.lsp">signature compatibility</link> rules.
</para>
<simpara>
As of PHP 8.4, an abstract class may declare an abstract property, either public or protected.
A protected abstract property may be satisfied by a property that is readable/writeable from either
protected or public scope.
</simpara>
<simpara>
An abstract property may be satisfied either by a standard property or by a property
with defined <link linkend="language.oop5.property-hooks">hooks</link>, corresponding to the required operation.
</simpara>
<example>
<title>Abstract method example</title>
<programlisting role="php">
<![CDATA[
<?php
abstract class AbstractClass
{
// Force extending class to define this method
abstract protected function getValue();
abstract protected function prefixValue($prefix);
// Common method
public function printOut()
{
print $this->getValue() . "\n";
}
}
class ConcreteClass1 extends AbstractClass
{
protected function getValue()
{
return "ConcreteClass1";
}
public function prefixValue($prefix)
{
return "{$prefix}ConcreteClass1";
}
}
class ConcreteClass2 extends AbstractClass
{
public function getValue()
{
return "ConcreteClass2";
}
public function prefixValue($prefix)
{
return "{$prefix}ConcreteClass2";
}
}
$class1 = new ConcreteClass1();
$class1->printOut();
echo $class1->prefixValue('FOO_'), "\n";
$class2 = new ConcreteClass2();
$class2->printOut();
echo $class2->prefixValue('FOO_'), "\n";
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
ConcreteClass1
FOO_ConcreteClass1
ConcreteClass2
FOO_ConcreteClass2
]]>
</screen>
</example>
<example>
<title>Abstract method example</title>
<programlisting role="php">
<![CDATA[
<?php
abstract class AbstractClass
{
// An abstract method only needs to define the required arguments
abstract protected function prefixName($name);
}
class ConcreteClass extends AbstractClass
{
// A child class may define optional parameters which are not present in the parent's signature
public function prefixName($name, $separator = ".")
{
if ($name == "Pacman") {
$prefix = "Mr";
} elseif ($name == "Pacwoman") {
$prefix = "Mrs";
} else {
$prefix = "";
}
return "{$prefix}{$separator} {$name}";
}
}
$class = new ConcreteClass();
echo $class->prefixName("Pacman"), "\n";
echo $class->prefixName("Pacwoman"), "\n";
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Mr. Pacman
Mrs. Pacwoman
]]>
</screen>
</example>
<example>
<title>Abstract property example</title>
<programlisting role="php">
<![CDATA[
<?php
abstract class A
{
// Extending classes must have a publicly-gettable property
abstract public string $readable {
get;
}
// Extending classes must have a protected- or public-writeable property
abstract protected string $writeable {
set;
}
// Extending classes must have a protected or public symmetric property
abstract protected string $both {
get;
set;
}
}
class C extends A
{
// This satisfies the requirement and also makes it settable, which is valid
public string $readable;
// This would NOT satisfy the requirement, as it is not publicly readable
protected string $readable;
// This satisfies the requirement exactly, so is sufficient.
// It may only be written to, and only from protected scope
protected string $writeable {
set => $value;
}
// This expands the visibility from protected to public, which is fine
public string $both;
}
?>
]]>
</programlisting>
</example>
<simpara>
An abstract property on an abstract class may provide implementations for any hook,
but must have either <literal>get</literal> or <literal>set</literal> declared but not defined (as in the example above).
</simpara>
<example>
<title>Abstract property example</title>
<programlisting role="php">
<![CDATA[
<?php
abstract class A
{
// This provides a default (but overridable) set implementation,
// and requires child classes to provide a get implementation
abstract public string $foo {
get;
set {
$this->foo = $value;
}
}
}
?>
]]>
</programlisting>
</example>
</sect1>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->
|