rfc:nested_classes

This is an old revision of the document!


PHP RFC: Nested Classes

Introduction

Following on from anonymous classes, this RFC proposes we support nested classes in PHP.

Proposal

A nested class is a class declared in the virtual namespace of another class:

class foo {
    class bar {
 
    }
}

foo\bar is a nested class in the virtual namespace of foo.

A nested class has the ability to declare it's accessibility to other classes in the same way as class members:

class foo {
    public class bar {
 
    }
}

The first and second examples given here are therefore the same, by default classes are public, just like class members.

The following describes the functionality of access modifiers for nested classes:

  • public - the class is accessible everywhere
  • private - the class may be accessed by any class declared in the outer class
  • protected - the class may be accessed by any class up to and including the outermost class

INSERT DIAGRAMS HERE

Syntax Example

The following is a syntax example and use case example; the primary use case for nested classes is black boxing: a nested class, interface, abstract etc should declare or contain functionality that is required for it's outer class to function, and support it's (public) API, but it should not always be exposed to the public.

In the following example, io\FileReader is a public API, the only public facing API method is ::getFileType, the remainder of the functionality is declared in a blackbox, only accessible where it must be accessible in order for io\FileReader to support public functionality.

<?php
namespace io {
 
    class FileReader {
        protected interface IOBuffer {}
 
        const UNKNOWN = 0;
        const ZIP = 1;
        const GZIP = 2;
 
        private class ZipFileReader {
            private class Buffer implements FileReader\IOBuffer {
                /* ... */
            }
 
            public function __construct() {
                $this->buffer = new FileReader\ZipFileReader\Buffer();
            }
        }
 
        private class GzFileReader {
            private class Buffer implements FileReader\IOBuffer {
                /* ... */
            }
 
            public function __construct() {
                $this->buffer = new FileReader\GzFileReader\Buffer();
            }
        }
 
        public function __construct($filename) {
            switch (FileReader::getFileType($filename)) {
                case FileReader::ZIP: {
                    $this->reader = new FileReader\ZipFileReader($filename);
                } break;
 
                case FileReader::GZIP: {
                    $this->reader = new FileReader\GzFileReader($filename);
                } break;
 
                /* ... */
            }
        }
 
        public static function getFileType($filename) {
            /** .. **/
            return FileReader::ZIP;
        }
    }
}
 
namespace {
    var_dump(new io\FileReader($argv[0]));
}
?>

More examples to come as the questions come in ...

Backward Incompatible Changes

A single test that was defined in Zend/tests to check that an error is emitted when you declare a nested class; in reality, nothing core is broken.

Proposed PHP Version(s)

5.6

SAPIs Impacted

All

Impact to Existing Extensions

Existing libraries that work directly with zend_class_entry structures will need to update to include the additional member of the struct “super”; the member is used to store a pointer to the class that created it.

Such an update should not cause any real inconvenience.

Reflection requires patching to be able to report information about outer classes and access levels.

Open Issues

Access to private statics members in outer classes (access to methods requires some adjustment too).

Proposed Voting Choices

We are not there yet ...

Implementation

References

Rejected Features

N/A

rfc/nested_classes.1380666368.txt.gz · Last modified: 2017/09/22 13:28 (external edit)