Private Methoden selber Basteln

  • Also hier ist mal ein kurzes Beispiel, wie ich das mit dem Pimpl gemeint habe, vielleicht ist dann klarer, dass es vorteilhaft sein kann.

    C-Quellcode

    1. /* vim: set ft=objc */
    2. #include <Cocoa/Cocoa.h>
    3. /************************* Versteckter Teil **/
    4. @interface Foo_intern : NSObject {
    5. }
    6. - (int) secret;
    7. - (int) number;
    8. @end
    9. @implementation Foo_intern
    10. /* "secret" ist eine echt private Methode, die
    11. * von aussen nicht verwendbar sein soll */
    12. - (int) secret {
    13. return 222;
    14. }
    15. /* "number" ist eine oeffentliche methode */
    16. - (int) number {
    17. return [self secret]*3;
    18. }
    19. @end
    20. /************************* Oeffentlicher Teil **/
    21. /* Im oeffentlichen header is kein hinweis
    22. * auf Foo_intern noetig! */
    23. @interface Foo : NSObject {
    24. @private
    25. id p_;
    26. }
    27. - (id) init;
    28. @end
    29. /* in der implementierung kann man einen
    30. * header von Foo_intern einbinden, das hier
    31. * bekommt ja auch niemand zu sehen */
    32. @implementation Foo
    33. - (id) init {
    34. self = [super init];
    35. if(self) {
    36. /* interne instanz anlegen */
    37. p_ = [[Foo_intern alloc] init];
    38. }
    39. return self;
    40. }
    41. /* oeffentliche methoden reichen einfach
    42. * nur weiter */
    43. - (int) number {
    44. return [p_ number];
    45. }
    46. /* "private" methoden fehlen! */
    47. @end
    48. /************************* Benutzung **/
    49. int main(int argc, char* argv[]) {
    50. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    51. Foo *f = [[Foo alloc] init];
    52. NSLog(@"%d\n", [f number]); ///< Wunderbar
    53. NSLog(@"%d\n", [f secret]); ///< Funktioniert nicht, crash!
    54. [pool drain];
    55. return 0;
    56. }
    Alles anzeigen

    Geht bestimmt noch eleganter, ist ja aber auch nur zu illustrationszwecken.
    C++
  • Original von zermelo
    Also hier ist mal ein kurzes Beispiel, wie ich das mit dem Pimpl gemeint habe, vielleicht ist dann klarer, dass es vorteilhaft sein kann.

    C-Quellcode

    1. /* vim: set ft=objc */
    2. #include <Cocoa/Cocoa.h>
    3. /************************* Versteckter Teil **/
    4. @interface Foo_intern : NSObject {
    5. }
    6. - (int) secret;
    7. - (int) number;
    8. @end
    9. @implementation Foo_intern
    10. /* "secret" ist eine echt private Methode, die
    11. * von aussen nicht verwendbar sein soll */
    12. - (int) secret {
    13. return 222;
    14. }
    15. /* "number" ist eine oeffentliche methode */
    16. - (int) number {
    17. return [self secret]*3;
    18. }
    19. @end
    20. /************************* Oeffentlicher Teil **/
    21. /* Im oeffentlichen header is kein hinweis
    22. * auf Foo_intern noetig! */
    23. @interface Foo : NSObject {
    24. @private
    25. id p_;
    26. }
    27. - (id) init;
    28. @end
    29. /* in der implementierung kann man einen
    30. * header von Foo_intern einbinden, das hier
    31. * bekommt ja auch niemand zu sehen */
    32. @implementation Foo
    33. - (id) init {
    34. self = [super init];
    35. if(self) {
    36. /* interne instanz anlegen */
    37. p_ = [[Foo_intern alloc] init];
    38. }
    39. return self;
    40. }
    41. /* oeffentliche methoden reichen einfach
    42. * nur weiter */
    43. - (int) number {
    44. return [p_ number];
    45. }
    46. /* "private" methoden fehlen! */
    47. @end
    48. /************************* Benutzung **/
    49. int main(int argc, char* argv[]) {
    50. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    51. Foo *f = [[Foo alloc] init];
    52. NSLog(@"%d\n", [f number]); ///< Wunderbar
    53. NSLog(@"%d\n", [f secret]); ///< Funktioniert nicht, crash!
    54. [pool drain];
    55. return 0;
    56. }
    Alles anzeigen

    Geht bestimmt noch eleganter, ist ja aber auch nur zu illustrationszwecken.


    aber das hier geht:

    Quellcode

    1. NSLog(@"%d\n", [[[Foo alloc] init] number]); ///< Wunderbar
    2. NSLog(@"%d\n", [[[NSClassFromString(@"Foo_intern") allc] init] secret]); ///< Wunderbar - kein crash ;-)
  • Original von gritsch

    Quellcode

    1. NSLog(@"%d\n", [[[Foo alloc] init] number]); ///< Wunderbar
    2. NSLog(@"%d\n", [[[NSClassFromString(@"Foo_intern") allc] init] secret]); ///< Wunderbar - kein crash ;-)

    Dafür musst du aber wissen, dass es "Foo_intern" gibt, sowie eine Methode namens "secret". Das findest Du natürlich mit class-dump etc. heraus - aber der Durchschnittsnutzer kann nicht "versehentlich" eine private Methode aufrufen.
    Üblicherweise sollte man ohnehin selten (überhaupt nicht?) Methoden haben, die nicht vom Zustand des Objektes abhängen. Entsprechend müsste jemand mit bösen Absichten anhand eines class-dumps den ganzen Wrapper nachimplementieren, dann jedoch mitsamt der "privaten" Methoden.
    C++
  • Original von johannesauer
    ich denke es geht einfach drarum, dass verhindert werden sollte, dass man versehentlich falsche Dinge tut. Und genau das finde ich nicht optimal gelöst...aber was solls, nichts ist Perfekt.

    Dann definiere doch einfach eine Kategorie mit den Methoden in der Implementierungsdatei. Bei der Datenkapselung geht es nicht um hundertprozentig sicheres Verstecken der Daten. Es darum, klare Schnittstellen nach Außen zu schaffen.
    „Meine Komplikation hatte eine Komplikation.“
  • Original von zermelo
    Original von gritsch

    Quellcode

    1. NSLog(@"%d\n", [[[Foo alloc] init] number]); ///< Wunderbar
    2. NSLog(@"%d\n", [[[NSClassFromString(@"Foo_intern") allc] init] secret]); ///< Wunderbar - kein crash ;-)

    Dafür musst du aber wissen, dass es "Foo_intern" gibt, sowie eine Methode namens "secret". Das findest Du natürlich mit class-dump etc. heraus - aber der Durchschnittsnutzer kann nicht "versehentlich" eine private Methode aufrufen.
    Üblicherweise sollte man ohnehin selten (überhaupt nicht?) Methoden haben, die nicht vom Zustand des Objektes abhängen. Entsprechend müsste jemand mit bösen Absichten anhand eines class-dumps den ganzen Wrapper nachimplementieren, dann jedoch mitsamt der "privaten" Methoden.


    wenn du dem user die funktionen gar nicht nennst (über den header) dann wird er sie auch net verwenden!
  • Original von johannesauer
    Hi,

    ich denke es geht einfach drarum, dass verhindert werden sollte, dass man versehentlich falsche Dinge tut. Und genau das finde ich nicht optimal gelöst...aber was solls, nichts ist Perfekt.

    Gruss,
    Johannes


    versehentlich methodennamen mittels class-dump und co rausgefunden oder was?
    wie gesagt, einfach die methode nicht in den header packen (den der verwender der klasse dann sieht) und am besten auch für dich selbst die methoden irgendwie kennzeichnen (ich pack wie apple immer ein "_" vorne dran oder auch 2 davon wenn eine solche methode nur von einer bereits "privaten" aufgerufen werden soll... ;)
  • ann definiere doch einfach eine Kategorie mit den Methoden in der Implementierungsdatei. Bei der Datenkapselung geht es nicht um hundertprozentig sicheres Verstecken der Daten. Es darum, klare Schnittstellen nach Außen zu schaffen.


    ja, so mache ich das auch. Das gibt dann wenigsten ein Warning...
  • Original von johannesauer
    Hey da fällt mir beim Thema Kennzeichnen gleich noch was anderes ein. Ist bei euch das #pragma seit Xcode 3.2 auch buggy? Bei mir macht der in der oberen Leiste nur Strunz...


    wunderbar unter 3.1.x (unter 10.5) ich muss ja arbeiten und nicht rumspielen (für mehr taugt 10.6.x im moment ja noch net)
  • Original von johannesauer
    Wie schaut das denn bei anderen Sprachen aus? Mich wundert es, das es das nicht wirklich gibt...die Lösung von Apple über extensions ist ja auch nicht optimal...aber wie gesagt, von der Runtime hab ich keine Ahnung.

    Der Grund, warum das nicht geht, ist, dass das ein Seiteneffekt wäre. Der Aufrufer gehört nicht zum Kontext, in dem die Methode läuft.


    Hätte das denn negative Auswirkungen?

    Seiteneffekte? Ja.
    de.wikipedia.org/wiki/Seitenef…ientierten_Programmierung
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von johannesauer
    Hi,

    der Anwendungsfall ist kein Spezieller, also kein Framework, ich würde einfach gerne den Zugriff einschränken. Dadurch könnte man einfach solidere Programme schreiben. Man kann natürlich gegenargumentieren und sagen, solange man nicht auf "private" methoden von aussen zugreift, reicht es, diese zu kennzeichnen. Aber das ist kein schöner Ansatz...mir ist einfach konzeptionell nicht klar, warum es geschützte Members gibt, aber keinen geschützten Methoden. Hat da jemand eine Begründung? Ist das konzeptionell so gewollt oder einfach eine Schwäche von Obj-C? Oder würde man sich andere Probleme einhandeln (schlechte Laufzeit, usw)?

    Gruss,
    Johannes

    Es geht ja darum, dass der Anwender nur diejenigen Methoden nimmt, die er nehmen soll. Wenn er eine private Methode nimmt, bekommt er eigentlich immer eine Warning. Er muss also gegen diese Warnung verstoßen. Das nennt man dann kriminelle Energie oder einfach saublöde. (Ja, ja, ich weiß, manche Sachen …)
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von zermelo
    Original von gritsch

    Quellcode

    1. NSLog(@"%d\n", [[[Foo alloc] init] number]); ///< Wunderbar
    2. NSLog(@"%d\n", [[[NSClassFromString(@"Foo_intern") allc] init] secret]); ///< Wunderbar - kein crash ;-)

    Dafür musst du aber wissen, dass es "Foo_intern" gibt, sowie eine Methode namens "secret". Das findest Du natürlich mit class-dump etc. heraus - aber der Durchschnittsnutzer kann nicht "versehentlich" eine private Methode aufrufen.
    Üblicherweise sollte man ohnehin selten (überhaupt nicht?) Methoden haben, die nicht vom Zustand des Objektes abhängen. Entsprechend müsste jemand mit bösen Absichten anhand eines class-dumps den ganzen Wrapper nachimplementieren, dann jedoch mitsamt der "privaten" Methoden.

    Die kann denn ohne Pimpl ein User versehentlich eine private Methode aufrufen?
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von johannesauer
    ann definiere doch einfach eine Kategorie mit den Methoden in der Implementierungsdatei. Bei der Datenkapselung geht es nicht um hundertprozentig sicheres Verstecken der Daten. Es darum, klare Schnittstellen nach Außen zu schaffen.


    ja, so mache ich das auch. Das gibt dann wenigsten ein Warning...

    Wenn an einem Stromkasten die Warnung hängt: 2Vorsicht Starkstrom" und jemand dennoch mit seinen Händchen reinpackt, nennst du das versehentlich?

    Kannst du mir kurz mal Absicht definieren?
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von johannesauer
    Hey da fällt mir beim Thema Kennzeichnen gleich noch was anderes ein. Ist bei euch das #pragma seit Xcode 3.2 auch buggy? Bei mir macht der in der oberen Leiste nur Strunz...

    Du meinst #pragma mark?

    Funktioniert bei mir.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Wenn an einem Stromkasten die Warnung hängt: 2Vorsicht Starkstrom" und jemand dennoch mit seinen Händchen reinpackt, nennst du das versehentlich?

    Kannst du mir kurz mal Absicht definieren?


    Ich fände es einfach schöner, wenn Methoden, genau wie Members, mit @protected zu kennzeichnen wären. Das wäre konsistent, und ein Error ist besser als ne Warnung. Und warum das nicht so ist verstehe ich nicht. Sind Extensions eigentlich was neues in Obj-C 2.0? Mir kommt das Extensions Konzept eher wie ein Notbehelf vor...das ist alles.

    Insgesamt kommt mir Obj-C und Cocoa sehr offen vor. Ich kenne mich mit den Konzepten nicht gut genug aus, und das IST sicher Teil des Konzeptes. Ein Beispiel ist z.B. KVC. Da muss man auch erst sagen, das man NICHT auf die Members zugreifen darf...aber wie gesagt, die Apple Jungs sind ja nicht doof, das hat sicher einen Sinn.

    Gruss,
    Johannes