2
votes

Méthode Matlab comme propriété

Existe-t-il un moyen d'écrire une classe Matlab qui a une de ses propres méthodes comme propriété? J'écris du code de simulation dans lequel la méthode de la classe (qui est en fait une équation physique) pourrait changer dans le développement futur, donc j'aimerais que les instances de classe archivées incluent la méthode.

Voici un pseudocode Matlab-ish. p>

classdef foo
   properties
      bar % some property
      baz % a property that contains the method baz
   end
   methods
       function out = baz() % the method I want to store
          stuff
       end
   end
end

Notez que je veux que les "trucs" soient d'une manière ou d'une autre stockés en tant que propriété, donc lorsque j'enregistrerai une instance, je connais la version de la méthode que j'ai utilisée.

Il est préférable qu'elle soit publique et non pas une propriété statique. Je souhaite sérialiser des instances.


7 commentaires

Vous voulez dire la méthode référence (c'est-à-dire la poignée de fonction) dans une propriété? Veuillez fournir un pseudocode (ou un code dans une autre langue) qui montre exactement ce que vous voulez réaliser et comment l'utiliser plus tard. Je mentionnerais également le type d'attributs de propriété et de méthode souhaités ( private , static , const etc.)


@ Dev-iL Je ne pense pas que je parle de référence de méthode. J'aimerais en fait stocker le contenu de la méthode, pas seulement sa poignée. Je suis nouveau dans l'utilisation de Matlab en tant que langage orienté objet, et je suis toujours amateur de la programmation OOL en général, donc ma terminologie ne manque peut-être pas. Je vais essayer d'écrire un pseudocode pour expliquer plus en détail.


Je pourrais ajouter une propriété comme "class version" et documenter des choses en dehors de la classe elle-même. Cependant, il y a une certaine propreté à l'avoir autonome.


Donc, fondamentalement, vous voulez enregistrer la définition de la classe (ou une partie de celle-ci), en texte brut, dans une propriété de la classe? Je dois dire que ce n'est pas quelque chose de commun en POO.


Le texte brut est une option, mais je pense qu'une fonction / méthode serait préférable. C'est en quelque sorte replier la classe sur elle-même, je suppose. J'essaie d'éviter de récupérer une instance archivée (sérialisée) créée avant un changement de méthode et d'utiliser naïvement le contenu d'une propriété telle que simulation_results sans pouvoir vérifier si l'instance a été générée à partir de une classe qui partage la définition d'une méthode donnée. Je pourrais utiliser le contrôle de version, mais cela nécessite que les choses soient suivies globalement, pas localement.


Je suppose que pour une simple «vérification de cohérence», le texte brut enregistré en tant que propriété et comparé à celui de la méthode actuelle n'est pas une très mauvaise voie. Je suppose qu'une version extrême de ceci serait simplement de cacher toute la définition de classe en tant que propriété ... comment cela fonctionnerait-il? (Désolé, je pense en quelque sorte à voix haute, ici.)


@Rico, vous devriez supprimer cet ajout de la question et l'afficher comme réponse (car il semble résoudre votre problème plutôt que d'être une clarification). BTW, je pense que cela pourrait valoir la peine d'écrire une fonction qui accepte un nom de fichier et un nom de fonction / méthode et ne renvoie que le code de la fonction.


3 Réponses :


1
votes
classdef foo
    properties (Dependent, SetAccess = 'private')
        baz % a property that contains the method baz
    end
    methods
       function out = bazMethod() % the method I want to store
          stuff
       end

       function bazOut = get.baz(self)
           bazOut = bazMethod();
       end
    end

end
It won't serialize the current method definition bazMethod, but if what you want is simply the definition, it kind of sounds like what you want is for baz to be a Dependent property.

1 commentaires

Merci. J'aimerais le sérialiser ... y a-t-il un moyen de le faire sans rendre baz privé? C'est intelligent, ce que vous avez fait ... proche de ce dont j'ai besoin.



3
votes

Si votre fonction est une seule expression, vous pouvez utiliser une fonction anonyme. Il sera enregistré dans un fichier MAT a > (Merci à gnovice pour l'avoir signalé). Donc par exemple:

f2 = foo;
f2.baz(2) % returns 20
load foo_test
f.baz(2)  % still returns 7.0711

Maintenant je peux faire:

classdef foo
   properties
      bar = 5
      baz_func = @(obj,x) baz_2022_08_04(obj,x) % could be private
   end
   methods
      function out = baz(obj,x)
         out = obj.baz_func(obj,x);
      end
      function out = baz_2019_05_22(obj,x) % could be private
         out = obj.bar * sqrt(x);
      end
      function out = baz_2022_08_04(obj,x) % could be private
         out = obj.bar * x.^2;
      end
   end
end

Et puis changer la définition de baz dans foo.m à baz = @ (x) x. ^ 2 , puis:

f = foo;
f.baz(2) % returns 7.0711
save foo_test f
clear

Si vous avez des fonctions plus complexes, vous pouvez le configurer de cette façon:

classdef foo
   properties
      bar = 5
      baz_func = @(obj,x) baz_2019_05_22(obj,x) % could be private
   end
   methods
      function out = baz(obj,x)
         out = obj.baz_func(obj,x);
      end
      function out = baz_2019_05_22(obj,x) % could be private
         out = obj.bar * sqrt(x);
      end
   end
end

Et maintenant:

f2 = foo;
f2.baz(2) % returns 4
load foo_test
f.baz(2)  % still returns 1.4142
f2.baz(2) % still returns 4

Dans le futur vous changez la fonction, mais vous conservez le code et créez une nouvelle fonction (privée) qui fait le calcul:

f = foo;
f.baz(2)  % returns 1.4142
save foo_test f
clear

La difficulté ici est de conserver l'ancien code en le changeant ... Mais vous pouvez rendre la fonction baz aussi complexe que vous le souhaitez ici. Maintenant:

classdef foo
   properties
      bar = 0
      baz = @(x)sqrt(x)
   end
end


6 commentaires

C'est assez intelligent! Cela sert efficacement mes objectifs, mais cela nécessite une vigilance dans le développement - si la méthode obsolète est supprimée, je pense que votre déclaration finale f.baz (2) générerait une erreur (méthode non définie). Tout bien considéré, ce n'est pas une mauvaise façon d'échouer, cependant. Cependant, si la méthode est modifiée sans changer de nom, nous ne saurions plus sur l'ancienne méthode, ni même qu'il y en avait une. +1, mais j'attendrai avant d'accepter car une autre solution pourrait encore atténuer ces limitations.


@Rico: Oui, vous devez conserver l'ancien code. De bonnes pratiques de programmation doivent être mises en place, y compris un outil de révision de code pour pouvoir revenir à une ancienne version du code si les choses tournent mal. Il n'y a malheureusement aucun moyen de stocker des fonctions dans un fichier MAT, à l'exception des fonctions anonymes qui sont limitées à une seule expression.


@Rico: Il existe peut-être un moyen de stocker un fichier M sous forme de texte dans l'objet et de l'écrire dans un fichier avant de l'appeler. Ce ne serait pas performant, mais ce serait probablement le moyen le plus sûr de stocker du code avec votre objet. Peut-être que si j'ai le temps plus tard, je jouerai avec cette idée et publierai une autre réponse. :)


Ha! Vous avez tapé ce dernier commentaire alors que je crachais quelque chose de similaire dans les commentaires sur la question initiale. Je pense qu'il y a quelque chose à dire pour utiliser une telle approche, en particulier dans le domaine du calcul scientifique, pour lequel la reproductibilité et la transparence sont des vertus. Merci d'avoir envisagé une réponse supplémentaire :)


Je crois avoir implémenté ce dont nous discutons dans mon édition OP. J'accepterai votre réponse de toute façon car c'est très informatif.


J'ai changé la modification mentionnée dans mon commentaire précédent en une réponse basée sur le commentaire de Dev-iL. Merci, @Cris Luengo, pour la suggestion.



1
votes

Sur la base du commentaire de Dev-iL et de la réponse de Cris, voici ce que j'ai fait, qui stocke l'intégralité du fichier classdef sous forme de texte brut dans la propriété class_definition .

classdef foo
   properties
      class_definition
   end
   methods
       function obj = foo()
         obj.class_definition = fileread([mfilename(),'.m']);
       end
       function out = baz() % the method I want to store
          stuff
       end
   end
end

Comme le suggère Dev-iL, écrire une fonction qui accepte un nom de fichier et un descripteur de fonction / méthode et renvoie le code de cette fonction (par opposition à l'ensemble du fichier classdef ) comme du texte brut probablement mieux répondre à la question initiale, donc j'accepterai une telle réponse si elle est publiée. Cette solution était suffisante pour mes besoins.


0 commentaires