@@ -427,7 +427,7 @@ pub struct ClassEntity<T: 'static> {
427427 state_constructor : Rc < StateConstructor > ,
428428 method_entities : Vec < MethodEntity > ,
429429 property_entities : Vec < PropertyEntity > ,
430- parent : Option < String > ,
430+ parent : Option < Box < dyn Fn ( ) -> & ' static ClassEntry > > ,
431431 interfaces : Vec < Interface > ,
432432 constants : Vec < ConstantEntity > ,
433433 bind_class : StateClass < T > ,
@@ -556,13 +556,54 @@ impl<T: 'static> ClassEntity<T> {
556556 /// # Examples
557557 ///
558558 /// ```no_run
559+ /// use phper::{
560+ /// classes::{ClassEntity, ClassEntry},
561+ /// modules::Module,
562+ /// php_get_module,
563+ /// };
564+ ///
565+ /// #[php_get_module]
566+ /// pub fn get_module() -> Module {
567+ /// let mut module = Module::new(
568+ /// env!("CARGO_CRATE_NAME"),
569+ /// env!("CARGO_PKG_VERSION"),
570+ /// env!("CARGO_PKG_AUTHORS"),
571+ /// );
572+ ///
573+ /// let foo = module.add_class(ClassEntity::new("Foo"));
574+ /// let mut bar = ClassEntity::new("Bar");
575+ /// bar.extends(&foo);
576+ ///
577+ /// module
578+ /// }
579+ /// ```
580+ pub fn extends < U : ' static > ( & mut self , parent : & StateClass < U > ) {
581+ let parent = parent. clone ( ) ;
582+ self . parent = Some ( Box :: new ( move || {
583+ let entry: & ' static ClassEntry =
584+ unsafe { std:: mem:: transmute ( parent. as_class_entry ( ) ) } ;
585+ entry
586+ } ) ) ;
587+ }
588+
589+ /// Register class to `extends` the parent class, by name. Similar to `extends`, this is
590+ /// useful for built-ins.
591+ ///
592+ /// # Examples
593+ ///
594+ /// ```no_run
559595 /// use phper::classes::{ClassEntity, ClassEntry};
560596 ///
561597 /// let mut class = ClassEntity::new("MyException");
562- /// class.extends ("Exception");
598+ /// class.extends_name ("Exception");
563599 /// ```
564- pub fn extends ( & mut self , parent_name : impl Into < String > ) {
565- self . parent = Some ( parent_name. into ( ) ) ;
600+ pub fn extends_name ( & mut self , name : impl Into < String > ) {
601+ let name = name. into ( ) ;
602+ self . parent = Some ( Box :: new ( move || {
603+ ClassEntry :: from_globals ( & name) . unwrap_or_else ( |_| {
604+ panic ! ( "Unable to resolve parent class: {}" , name) ;
605+ } )
606+ } ) ) ;
566607 }
567608
568609 /// Register class to `implements` the interface, due to the class can
@@ -631,11 +672,8 @@ impl<T: 'static> ClassEntity<T> {
631672 #[ allow( clippy:: useless_conversion) ]
632673 pub ( crate ) unsafe fn init ( & self ) -> * mut zend_class_entry {
633674 unsafe {
634- let parent: * mut zend_class_entry = if let Some ( ref name) = self . parent {
635- let entry = ClassEntry :: from_globals ( name) . unwrap_or_else ( |err| {
636- panic ! ( "Unable to resolve parent class: {}: {}" , name, err) ;
637- } ) ;
638- entry. as_ptr ( ) as * mut _
675+ let parent: * mut zend_class_entry = if let Some ( ref parent_fn) = self . parent {
676+ parent_fn ( ) . as_ptr ( ) as * mut _
639677 } else {
640678 null_mut ( )
641679 } ;
0 commit comments