¿Hay tipos enumerados en MATLAB? si no, cuales son las alternativas?¿Cómo creo tipos enumerados en MATLAB?
Respuesta
, usted puede obtener algunas de las funciones de MATLAB con las clases de nuevo estilo:
classdef (Sealed) Colors
properties (Constant)
RED = 1;
GREEN = 2;
BLUE = 3;
end
methods (Access = private) % private so that you cant instantiate
function out = Colors
end
end
end
esto no es realmente un tipo, pero desde MATLAB se escribe sin apretar, si utiliza números enteros, se pueden hacer cosas que aproximarla:
line1 = Colors.RED;
...
if Colors.BLUE == line1
end
En este caso, "enumeraciones" MATLAB están cerca de las enumeraciones de tipo C - sintaxis sustituto de números enteros.
Con el uso cuidadoso de métodos estáticos, incluso puede hacer que las enums de MATLAB se acerquen a la sofisticación de Ada, pero desafortunadamente con una sintaxis más torpe.
Si usted quiere hacer algo similares a lo Marc sugirió, podría simplemente hacer una structure para representar sus tipos enumerados en lugar de toda una clase nueva:
colors = struct('RED',1,'GREEN',2,'BLUE',3);
Uno de los beneficios es que usted puede fácilmente acceder a las estructuras de dos maneras diferentes. Se puede especificar un campo directamente utilizando el nombre del campo:
a = colors.RED;
o puede utilizar dynamic field names si tiene el nombre de campo en una cadena:
a = colors.('RED');
En verdad, hay algunas ventajas a hacer lo que sugirió Marc y crear una clase completamente nueva para representar un objeto "enumerado":
- Puede controlar cómo se modifica el objeto.
- Puede mantener la definición en un solo lugar y utilizarla fácilmente en varios lugares.
- Puede controlar las fallas y hacerlas más "elegantes", como devolver una matriz vacía si intenta acceder a un campo inexistente (en lugar de arrojar un error).
Sin embargo, si no necesita ese tipo de complejidad y solo necesita hacer algo rápido, una estructura es probablemente la implementación más sencilla y directa. También funcionará con versiones anteriores de MATLAB que no usan el marco de OOP más nuevo.
Si tiene acceso a Statistics Toolbox, puede considerar el uso de categorical object.
Puede hacer una clase de Matlab que se comporte como Java's old typesafe enum pattern. Una modificación de Marc's solution podría llevarlo desde los typedefs de tipo C a más como enum de tipo de estilo Java. En esta versión, los valores en las constantes son objetos de Color tipeados.
El upsides:
- El tipo se puede comprobar (en tiempo de ejecución) por == y otras operaciones para prevenir comparación accidental a valores numéricos primas o de otros tipos de enumeraciones.
- Puede verificar explícitamente el tipo de sus variables (en tiempo de ejecución).
- Los valores se muestran con nombres legibles en lugar de los códigos opacos.
- Las operaciones como mean() y std() que no tienen sentido en las enumeraciones no están permitidas.
Desventajas:
- más larga definición de clase. Pero, esto es todo repetitivo, y puede reutilizarse para cualquier otra clase enum, cambiando solo el nombre de la clase y las propiedades de Constante.
- Estas enumeraciones no se pueden utilizar directamente en bloques de interruptores. Necesitas sacar el código, lo que pierde algún tipo de seguridad.
- Los objetos serán más lentos que los primitivos. Pertinente si está usando constantes dentro de los bucles.
En general, no sé qué enfoque es mejor. No lo he usado en la práctica.
classdef (Sealed) Color
%COLOR Example of Java-style typesafe enum for Matlab
properties (Constant)
RED = Color(1, 'RED');
GREEN = Color(2, 'GREEN');
BLUE = Color(3, 'BLUE');
end
properties (SetAccess=private)
% All these properties are immutable.
Code;
Name;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
methods (Access = private)
%private so that you can't instatiate directly
function out = Color(InCode, InName)
out.Code = InCode;
out.Name = InName;
end
end
methods (Static = true)
function needa(obj)
%NEEDA Asserts that obj must be a Color
if ~isa(obj, mfilename)
error('Input must be a %s; got a %s', mfilename, class(obj));
end
end
end
methods (Access = public)
function display(obj)
disp([inputname(1) ' =']);
disp(obj);
end
function disp(obj)
if isscalar(obj)
disp(sprintf('%s: %s (%d)', class(obj), obj.Name, obj.Code));
else
disp(sprintf('%s array: size %s', class(obj), mat2str(size(obj))));
end
end
function out = eq(a, b)
%EQ Basic "type-safe" eq
check_type_safety(a, b);
out = [a.Code] == [b.Code];
end
function [tf,loc] = ismember(a, b)
check_type_safety(a, b);
[tf,loc] = ismember([a.Code], [b.Code]);
end
function check_type_safety(varargin)
%CHECK_TYPE_SAFETY Check that all inputs are of this enum type
for i = 1:nargin
if ~isa(varargin{i}, mfilename)
error('Non-typesafe comparison of %s vs. %s', mfilename, class(varargin{i}));
end
end
end
end
end
Aquí hay una función para ejercitarlo.
function do_stuff_with_color(c)
%DO_STUFF_WITH_COLOR Demo use of the Color typesafe enum
Color.needa(c); % Make sure input was a color
if (c == Color.BLUE)
disp('color was blue');
else
disp('color was not blue');
end
% To work with switch statements, you have to explicitly pop the code out
switch c.Code
case Color.BLUE.Code
disp('blue');
otherwise
disp(sprintf('some other color: %s', c.Name));
end
Ejemplo de uso:
>> Color.RED == Color.RED
ans =
1
>> Color.RED == 1
??? Error using ==> Color>Color.check_type_safety at 55
Non-typesafe comparison of Color vs. double
Error in ==> Color>Color.eq at 44
check_type_safety(a, b);
>> do_stuff_with_color(Color.BLUE)
color was blue
blue
>> do_stuff_with_color(Color.GREEN)
color was not blue
some other color: GREEN
>> do_stuff_with_color(1+1) % oops - passing the wrong type, should error
??? Error using ==> Color>Color.needa at 26
Input must be a Color; got a double
Error in ==> do_stuff_with_color at 4
Color.needa(c); % Make sure input was a color
>>
Un capricho menor en ambos enfoques: la convención C de poner la constante en el lado izquierdo de la "==" para evitar la mala asignación no ayuda tanto aquí En Matlab, si accidentalmente usas "=" con esta constante en el LHS, en lugar de un error, creará una nueva variable de estructura local llamada Colors, y enmascarará la clase enum.
>> Colors.BLUE = 42
Colors =
BLUE: 42
>> Color.BLUE = 42
Color =
BLUE: 42
>> Color.RED
??? Reference to non-existent field 'RED'.
Muy agradable, Andrew. Me preguntaba cuándo entraría. – Marc
También podría utilizar las clases enum de Java desde su código Matlab. Defínelos en Java y colóquelos en el javaclasspath de Matlab.
// Java class definition
package test;
public enum ColorEnum {
RED, GREEN, BLUE
}
Puede referenciarlos por nombre en código M.
mycolor = test.ColorEnum.RED
if mycolor == test.ColorEnum.RED
disp('got red');
else
disp('got other color');
end
% Use ordinal() to get a primitive you can use in a switch statement
switch mycolor.ordinal
case test.ColorEnum.BLUE.ordinal
disp('blue');
otherwise
disp(sprintf('other color: %s', char(mycolor.toString())))
end
Sin embargo, no tomará comparaciones con otros tipos. Y la comparación con la cadena tiene un tamaño de retorno impar.
>> test.ColorEnum.RED == 'GREEN'
ans =
0
>> test.ColorEnum.RED == 'RED'
ans =
1 1 1
No es en realidad una palabra clave en MATLAB R2009b llama 'enumeración'. Parece que no está documentado, y no puedo decir que sé cómo usarlo, pero la funcionalidad probablemente esté allí.
Puede encontrarlo en matlabroot\toolbox\distcomp\examples\+examples
classdef(Enumeration) DmatFileMode < int32
enumeration
ReadMode(0)
ReadCompatibilityMode(1)
WriteMode(2)
end
<snip>
end
Esta es la forma correcta de hacerlo si va a realizar la generación de código. Se documenta mejor en la documentación de Simulink en "Definición de un tipo de datos enumerados". –
Después de probar las otras sugerencias en esta página, que aterrizó en el enfoque totalmente orientado a objetos de Andrew. Muy bien, gracias Andrew.
En caso de que alguien esté interesado, sin embargo, hice (lo que creo) algunas mejoras. En particular, eliminé la necesidad de especificar dos veces el nombre del objeto enum. Los nombres ahora se derivan usando la reflexión y el sistema de metaclase. Además, las funciones eq() y ismember() se volvieron a escribir para devolver valores de retorno con la forma adecuada para matrices de objetos enum. Y finalmente, la función check_type_safety() se modificó para hacerla compatible con los directorios de paquetes (por ejemplo, espacios de nombres).
parece funcionar muy bien, pero que me haga saber lo que piensa:
classdef (Sealed) Color
%COLOR Example of Java-style typesafe enum for Matlab
properties (Constant)
RED = Color(1);
GREEN = Color(2);
BLUE = Color(3);
end
methods (Access = private) % private so that you can''t instatiate directly
function out = Color(InCode)
out.Code = InCode;
end
end
% ============================================================================
% Everything from here down is completely boilerplate - no need to change anything.
% ============================================================================
properties (SetAccess=private) % All these properties are immutable.
Code;
end
properties (Dependent, SetAccess=private)
Name;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
methods
function out = eq(a, b) %EQ Basic "type-safe" eq
check_type_safety(a, b);
out = reshape([a.Code],size(a)) == reshape([b.Code],size(b));
end
function [tf,loc] = ismember(a, b)
check_type_safety(a, b);
[tf,loc] = ismember(reshape([a.Code],size(a)), [b.Code]);
end
function check_type_safety(varargin) %CHECK_TYPE_SAFETY Check that all inputs are of this enum type
theClass = class(varargin{1});
for ii = 2:nargin
if ~isa(varargin{ii}, theClass)
error('Non-typesafe comparison of %s vs. %s', theClass, class(varargin{ii}));
end
end
end
% Display stuff:
function display(obj)
disp([inputname(1) ' =']);
disp(obj);
end
function disp(obj)
if isscalar(obj)
fprintf('%s: %s (%d)\n', class(obj), obj.Name, obj.Code);
else
fprintf('%s array: size %s\n', class(obj), mat2str(size(obj)));
end
end
function name=get.Name(obj)
mc=metaclass(obj);
mp=mc.Properties;
for ii=1:length(mp)
if (mp{ii}.Constant && isequal(obj.(mp{ii}.Name).Code,obj.Code))
name = mp{ii}.Name;
return;
end;
end;
error('Unable to find a %s value of %d',class(obj),obj.Code);
end;
end
end
Gracias, Mason
A partir de R2010b, MATLAB soporta enumeraciones.
Ejemplo de la documentation:
classdef Colors
properties
R = 0;
G = 0;
B = 0;
end
methods
function c = Colors(r, g, b)
c.R = r; c.G = g; c.B = b;
end
end
enumeration
Red (1, 0, 0)
Green (0, 1, 0)
Blue (0, 0, 1)
end
end
para lectores futuros, esta probablemente sea la respuesta aceptada (todas las soluciones son buenas) – Amro
Este es un ejemplo más complicado de la clase enum. Se puede encontrar uno más simple dentro de la documentación. – KronoS
Url para el ejemplo más simple @KronoS mencionado: [link] (http://www.mathworks.de/de/help/matlab/matlab_oop/enumerations.html) – JaBe
Si necesita los tipos enumerados sólo para pasar a C# o ensamblado de .NET, se puede construir y transmitir las enumeraciones con MATLAB 2010:
A = NET.addAssembly(MyName.dll)
% suppose you have enum called "MyAlerts" in your assembly
myvar = MyName.MyAlerts.('value_1');
también puede consultar la respuesta oficial de MathWorks al
// the enum "MyAlerts" in c# will look something like this
public enum MyAlerts
{
value_1 = 0,
value_2 = 1,
MyAlerts_Count = 2,
}
Toys = {'Buzz', 'Woody', 'Rex', 'Hamm'};
Toys{3}
ans = 'Rex'
- 1. Rails Tipos enumerados o alternativas
- 2. valores de Asignación de tipos enumerados
- 3. ¿Cómo puedo extender un molde léxico para admitir tipos enumerados?
- 4. ¿Enumerados en AS3/Flash/Flex?
- 5. ¿Cómo creo una matriz de valores regularmente espaciados en MATLAB?
- 6. ¿Cómo creo una GUI con pestañas en MatLab?
- 7. ¿Cómo creo un diccionario que contiene diferentes tipos en C#
- 8. Componer enumerados en el enumerador
- 9. ¿Enumerados o tablas?
- 10. Pasar de los tipos Java a los tipos MATLAB
- 11. Cómo pasar valores enumerados a un servicio web
- 12. Enumerados y cuadros combinados en C#
- 13. ¿Puedo asignar tipos a las propiedades de clase en MATLAB?
- 14. ¿Cómo creo una matriz de imágenes con una línea dibujada en MATLAB?
- 15. Enumerados y conflictos de nomenclatura de propiedades
- 16. Suprimir los nombres de directorio enumerados con DIR
- 17. ¿Cómo se iteran los tipos enumerados inicializados con Delphi 6 y se evita el error "fuera de límites"?
- 18. ¿Cómo creo "deshacer" en C++?
- 19. Secciones personalizadas para objetos enumerados de matriz en NSOutlineView
- 20. JavaScript: ¿Cómo creo JSONP?
- 21. ¿Cómo creo parches binarios?
- 22. ¿Cómo ordenar matrices de estructuras en MATLAB?
- 23. ¿Cómo usar libsvm en Matlab?
- 24. ¿Cómo emulo el comportamiento 'incluir' en MATLAB?
- 25. ¿Cómo creo un temporizador en WPF?
- 26. ¿Cómo creo CSS dinámico en Rails?
- 27. ¿Cómo creo sesiones persistentes en PHP?
- 28. ¿Cómo creo sombras baratas en OpenGL?
- 29. ¿Cómo creo un índice DESC en MySQL?
- 30. ¿Cómo creo una tabla hash en Java?
acaba de ser conscientes de los posibles golpes de rendimiento cuando se utiliza el nuevo material orientado a objetos. En mi experiencia, introdujo una sobrecarga significativa. Sin embargo, realmente depende de lo que estés haciendo. –
En realidad, para las clases simples, efectivamente no hay penalización de tiempo en comparación con el uso de muchas estructuras globales. Sin embargo, el ahorro de tiempo de desarrollo para buenas prácticas es sustancial, y raramente es el tiempo de ejecución como un problema. El hardware es barato. Las personas que escriben el software no lo son. – Marc