Borrar filtros
Borrar filtros

Class initialization is fundamentally broken, but here's a workaround

2 visualizaciones (últimos 30 días)
Jeffrey
Jeffrey el 8 de Mzo. de 2017
Comentada: Christopher Beebe el 22 de Mayo de 2020
The class constructor methodology is fundamentally unsafe and broken, because a subclass' properties are not initialized before the superclass calls a method that requires those properties.
Specifically, if a subclass overrides a method called from the superclass' constructor, this will result in a method being called before all the properties on the object are initialized. It is fundamentally unsafe, yet this is the recommendation in the documentation and apparently a language requirement!
Here's a simple example that creates two class, A and subclass B.
classdef A < handle
properties
x
end
methods
function self = A(x)
self.x = x;
self.myMethod();
end
function self = myMethod(self)
fprintf('I am an instance of class A with property x=%d\n',self.x);
end
end
end
and now class B,
classdef B < A
properties
y
end
methods
function self = B(x,y)
self@A(x);
self.y = y;
end
function self = myMethod(self)
fprintf('I am an instance of class B with properties x=%d and y=%d\n',self.x,self.y);
end
end
end
In the attached example, try
a = A(1);
b = B(1,2);
and you will see that the method 'myMethod()' tries to use the uninitialized property 'y'.
The correct way to solve this problem is to require that subclasses initialize their own stored properties before calling the superclass constructor. Of course, Matlab's compiler does not allow this, making the correct solution impossible.
Now I will post what I think is a reasonable workaround, until Matlab fixes this problem.
  2 comentarios
Jeffrey
Jeffrey el 8 de Mzo. de 2017
Editada: Jeffrey el 8 de Mzo. de 2017
The most general workaround that I could come up with requires a specific design pattern, as follows.
Class A would now be defined as,
classdef A < handle
properties
x
end
methods
% Subclass needs to override this function to initialize the stored
% properties introduced by the subclass. Once complete, it needs to
% call the superclass implementation of this method.
function self = initStoredProperties(self,x,args)
self.x = x;
end
function self = A(x, varargin)
self.initStoredProperties(x,varargin);
self.myMethod();
end
function self = myMethod(self)
fprintf('I am an instance of class A with property x=%d\n',self.x);
end
end
end
and Class B as,
classdef B < A
properties
y
end
methods
% Subclass needs to override this function to initialize the stored
% properties introduced by the subclass. Once complete, it needs to
% call the superclass implementation of this method.
function self = initStoredProperties(self,x,args)
self.y = args{1};
initStoredProperties@A(self,x,args);
end
function self = B(x,y)
self@A(x,y);
% Now go ahead an override stored properties values from the
% super class
end
function self = myMethod(self)
fprintf('I am an instance of class B with properties x=%d and y=%d\n',self.x,self.y);
end
end
end
That is, all subclasses need to override initStoredProperties() and use that to set any new stored properties defined by the subclass, and then call the superclass implementation.
Store properties initialized by the superclass can be overridden after the subclass calls the superclass constructor.
This design pattern should ensure that everything is properly initialized before any methods get called. This pattern is taken from Swift .
Hope this helps someone else!
Christopher Beebe
Christopher Beebe el 22 de Mayo de 2020
Thanks for point this out. As of 2019b, the problem is solved by adding a < handle after the classdef ClassName declaration.

Iniciar sesión para comentar.

Respuestas (0)

Categorías

Más información sobre Subclass Definition en Help Center y File Exchange.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by