@@ -28,6 +28,8 @@ final class Property
2828	private  ?string  $ typenull ;
2929	private  bool  $ nullablefalse ;
3030	private  bool  $ initializedfalse ;
31+ 	private  bool  $ finalfalse ;
32+ 	private  bool  $ abstractfalse ;
3133
3234
3335	public  function  setValue (mixed  $ valstatic 
@@ -99,11 +101,46 @@ public function isInitialized(): bool
99101	}
100102
101103
104+ 	public  function  setFinal (bool  $ statetrue ): static 
105+ 	{
106+ 		$ this final  = $ state
107+ 		return  $ this 
108+ 	}
109+ 110+ 111+ 	public  function  isFinal (): bool 
112+ 	{
113+ 		return  $ this final ;
114+ 	}
115+ 116+ 117+ 	public  function  setAbstract (bool  $ statetrue ): static 
118+ 	{
119+ 		$ this abstract  = $ state
120+ 		return  $ this 
121+ 	}
122+ 123+ 124+ 	public  function  isAbstract (): bool 
125+ 	{
126+ 		return  $ this abstract ;
127+ 	}
128+ 129+ 102130	/** @throws Nette\InvalidStateException */ 
103131	public  function  validate (): void 
104132	{
105133		if  ($ this readOnly  && !$ this type ) {
106134			throw  new  Nette \InvalidStateException ("Property  \$$ this name : Read-only properties are only supported on typed property. " );
135+ 136+ 		} elseif  ($ this abstract  && $ this final ) {
137+ 			throw  new  Nette \InvalidStateException ("Property  \$$ this name  cannot be abstract and final at the same time. " );
138+ 139+ 		} elseif  (
140+ 			$ this abstract 
141+ 			&& !Nette \Utils \Arrays::some ($ this getHooks (), fn ($ hook$ hookisAbstract ())
142+ 		) {
143+ 			throw  new  Nette \InvalidStateException ("Property  \$$ this name : Abstract property must have at least one abstract hook. " );
107144		}
108145	}
109146
0 commit comments