2011-06-23 15 views
15

¿Hay alguna forma de definir variables de miembros estáticos en las clases de MATLAB?¿Cómo obtener variables miembro estáticas en clases MATLAB?

Esto no funciona:

classdef A 

    properties (Static) 
     m = 0; 
    end 
end 

Se sugiere utilizar la palabra clave "constante" en lugar de "estática", las propiedades constantes no pueden ser modificados. Quiero una variable común a todos los objetos de la clase A y quiero poder modificar esa variable en los métodos de la clase A.

Entonces, lo que necesito es una variable de miembro estática privada. ¿Hay alguna forma de obtenerlo en MATLAB?


descubrí que una solución se puede hacer usando variables persistentes en funciones miembro estáticas.

En este caso, debe heredar todas sus clases de una clase base como la siguiente.

classdef object < handle 

    properties (GetAccess = 'public', SetAccess = 'private') 
     id 
    end 

    methods (Access = 'protected') 
     function obj = object() 
      obj.id = object.increment(); 
     end 
    end 

    methods (Static, Access = 'private') 
     function result = increment() 
      persistent stamp; 
      if isempty(stamp) 
       stamp = 0; 
      end 
      stamp = stamp + uint32(1); 
      result = stamp; 
     end 
    end 
end 
+1

no es para ello AFAIK, pero funciona [persistente] (http://www.mathworks.com/help/techdoc/ref/persistent.html)? –

+1

Sí, obtuve una solución con una variable persistente en una función miembro estática. – Vahagn

+1

debe publicarlo como respuesta para los interesados ​​en esta pregunta –

Respuesta

15

No puede, es por diseño. Debe usar una variable persistent (técnica de MATLAB como aplicada en 1980 en el año 2011).

Para ser completo, debo mencionar que en realidad existe a partir de 2010b un modificador de propiedad static no documentado y probablemente ya no sea compatible.

Para el fondo ver here la respuesta de Dave Foti, MATLAB director del grupo OO:

En MATLAB, las clases pueden definir constantes propiedades, pero no "estática" propiedades en el sentido de otros lenguajes como C++ . Hubo versiones beta que experimentaron con las propiedades "Estáticas" y el atributo no documentado permanece desde a continuación. Sin embargo, el atributo Estático es no documentado, no debe utilizarse, y probablemente se eliminará en una futura versión de MATLAB. R2008a lo implementa como sinónimo de constante y proporciona sin funcionalidad adicional más allá de el comportamiento documentado de las propiedades de Constant .

Las propiedades constantes no pueden cambiarse a partir del valor inicial especificado en la declaración de propiedad. Hay un par de razones por las cuales MATLAB funciona de la forma en que lo hace. Primero, MATLAB tiene reglas de larga data que las variables siempre preceden sobre los nombres de funciones y clases y que las declaraciones de asignación introducen una variable si aún no existe una. Por lo tanto, cualquier expresión de la forma "A.B = C" introducirá una nueva variable A que es una matriz de estructura que contiene un campo B cuyo valor es C. Si "A.B = C" podría referirse a una propiedad estática de clase A, entonces la clase A tomaría precedente sobre la variable A y esta sería un incompatibilidad muy significativa con versiones anteriores de MATLAB. Esto significaría que una m -file que contiene la instrucción de asignación "AB = C" podría tener su significado cambió por la introducción de una clase llamada a algún lugar en el camino MATLAB. MATLAB programadores han siempre ha sido capaz de confiar en la asignación declaraciones que introducen variables que sombrear cualquier otro uso del mismo nombre.

En segundo lugar, hemos observado que los datos estáticos rara vez se utilizan en otras clases excepto como datos privados dentro de la clase o como constantes públicas. Para el ejemplo , una encuesta de varias bibliotecas de clases Java encontró que todos los campos estáticos públicos también eran finales. En MATLAB, las propiedades de Constant pueden ser utilizadas como campos "públicos finales estáticos" en Java. Para datos internos a una clase , MATLAB ya tiene variables persistentes que se pueden crear dentro de de métodos privados o protegidos o funciones locales utilizadas de forma privada por una clase . También hay buenas razones para evitar los datos estáticos en MATLAB donde es posible . Si una clase tiene datos estáticos, puede ser difícil utilizar la misma clase en múltiples aplicaciones porque los datos estáticos pueden ser una fuente de conflictos entre las aplicaciones . En algunos otros lenguajes, esto es un problema menor porque diferentes aplicaciones se compilan por separado en en ejecutables que se ejecutan en diferentes procesos con diferentes copias de datos estáticos de clase. En MATLAB, con frecuencia muchas aplicaciones diferentes se pueden ejecutar en el mismo proceso y entorno con una sola copia de cada clase.

11

Aquí hay una manera directa de crear una propiedad estática en Matlab. La única diferencia entre esta implementación y una propiedad estática verdadera hipotética (pero imposible, ver la respuesta de Mikhail) es la sintaxis para establecer la variable miembro.

classdef StaticVarClass 
    methods (Static = true) 
     function val = staticVar(newval) 
      persistent currentval; 
      if nargin >= 1 
       currentval = newval; 
      end 
      val = currentval; 
     end 
    end 
end 

Ahora el staticVar propiedad estática se puede leer a través de:

StaticVarClass.staticVar 

... y definirse a través de:

StaticVarClass.staticVar(newval); 

Así, por ejemplo, este es el resultado esperado de una prueba de esta funcionalidad:

>> StaticVarClass.staticVar 
    ans = 
     [] 
>> StaticVarClass.staticVar('foobar') 
    ans = 
     foobar 
>> StaticVarClass.staticVar 
    ans = 
     foobar 
>> 

Este enfoque funciona igual de bien para propiedades privadas estáticas como las solicitadas, pero el código de demostración es un poco más largo. Tenga en cuenta que esto no es una clase de control (aunque también funcionaría perfectamente en una clase de control).

classdef StaticVarClass 
    methods (Access = private, Static = true) 
     function val = staticVar(newval) 
      persistent currentval; 
      if nargin >= 1 
       currentval = newval; 
      end 
      val = currentval; 
     end 
    end 

    methods 
     function this = setStatic(this, newval) 
      StaticVarClass.staticVar(newval); 
     end 

     function v = getStatic(this) 
      v = StaticVarClass.staticVar; 
     end 
    end 
end 

...y la prueba:

>> x = StaticVarClass 
    x = 
     StaticVarClass with no properties. 
     Methods 
>> x.getStatic 
    ans = 
     [] 
>> x.setStatic('foobar') 
    ans = 
     StaticVarClass with no properties. 
     Methods 
>> x.getStatic 
    ans = 
     foobar 
>> 
0

(sólo para informar a) hay (otro?) manera de crear datos estática como en MATLAB

suponga que tiene una clase de "manejar" la cual su nombre es " coche" si desea que el tipo de auto para tener datos estáticos, usted podría construir otra clase de mango y utilizarlo en la composición de tiro categoría de coches, esta última clase funciona como un conjunto de datos estáticos de la clase de coche

classdef car<handle 
    properties 
     static_data:STATIC_DATA_HOLDER; 
    end 
end 

classdef STATIC_DATA_HOLDER<handle 
    properties 
     data 
    end 
end 

esta manera cuando creas primera instancia de un auto class, se creará una instancia de STATIC_DATA_HOLDER y cuando cree una segunda instancia de clase de vehículo, se utilizará la clase STATIC_DATA_HOLDER creada anteriormente.

estos códigos probado con "MATLAB 2013b"

0

Otra solución para conseguir algo así como propiedades estáticas es utilizar el hecho de que el código de inicialización de variables miembro sólo se ejecuta una vez cuando se carga el archivo de clase. Eso significa que, si usted tiene una definición como

classdef foo 
    properties 
     stuff = some_function() 
    end 
end 

continuación some_function se invoca sólo una vez, y si se devuelve un objeto de tipo de clase, esto será compartida por todas las instancias. He añadido una aplicación de ejemplo que muestra cómo se puede utilizar:

classdef ClassWithStaticMembers 
    properties 
     classvars = StaticVarContainer('foo', 0, 'bar', 2); 
     othervar 
    end 
    methods 
     function obj=ClassWithStaticMembers(var) 
      obj.othervar = var; 
     end 
    end 
end 

classdef StaticVarContainer < dynamicprops 
    methods 
     function obj=StaticVarContainer(varargin) 
      for i=1:2:numel(varargin) 
       obj.addprop(varargin{i}); 
       obj.(varargin{i}) = varargin{i+1}; 
      end 
     end 
    end 
end 

Si ejecuta este código de ejemplo

obj1 = ClassWithStaticMembers(3); 
obj2 = ClassWithStaticMembers(5); 
obj1.classvars.foo = [2,3]; 

obj1.othervar 
obj1.classvars 

obj2.othervar 
obj2.classvars 

verá, que es de hecho classvars compartido. Creo que esta solución es mucho mejor que utilizar variables persistentes en las funciones, ya que puede reutilizar StaticVarContainer tantas veces como desee, es más fácil de usar y, además, ve directamente la inicialización de las variables estáticas en la sección de propiedades.

Para obtener el resultado, lo que se desea en la pregunta de la OP (es decir, la aplicación de un contador de objetos) la propiedad compartida puede hacerse Constant, de manera que se pueda hacer referencia sin una instancia a la mano:

classdef ClassWithCounter 
    properties (Constant) 
     static = StaticVarContainer('counter', 0); 
    end 
    methods 
     function obj=ClassWithCounter() 
      obj.static.counter = obj.static.counter + 1; 
     end 
    end 
end 

clear all 
obj1 = ClassWithCounter(); 
obj2 = ClassWithCounter(); 
obj3 = ClassWithCounter(); 

ClassWithCounter.static.counter 

Tenga en cuenta que el atributo Constant solo significa que, por ejemplo obj1.static no se puede cambiar, pero no afecta a obj1.static.counter, que no es constante y se puede configurar según lo desee el corazón.