Push-Nachrichten von MacTechNews.de
Würden Sie gerne aktuelle Nachrichten aus der Apple-Welt direkt über Push-Nachrichten erhalten?
Forum>Entwickler>Zugriff bei Vererbung auf private Propertys?

Zugriff bei Vererbung auf private Propertys?

lenn1
lenn123.11.1122:20
Habe mir mal wieder ein paar iTunesU Tutorien angeschaut und gemerkt, dass es mittlerweile gängige Konvention ist, dass man seine privaten Propertys und auch privaten Methoden nun als solche deklariert in ObjC.

Ich finde diese Regelung gut, da ich es eh aus anderen Programmiersprachen gewohnt bin so zu handeln.
Ich habe nun aber ein Problem mit der Vererbung dieser.
Ich habe nämlich überhaupt keinen Zugriff auf private Propertys.

Vererbe ich die Klasse unten an eine andere funktioniert weder
_myPrivateFoo = 20;
noch
self.myPrivateFoo = 20;

Gibts es da abhilfe?
Gruß
Lenn1

//FooBar.h
#import <Foundation/Foundation.h>

@interface FooBar : NSObject
-(void)doSomeThingWithThisNumber:(NSInteger)aNumber;
@end
// FooBar.m

#import "FooBar.h"


@interface FooBar()
@property NSInteger myPrivateFoo;
@end


@implementation FooBar
@synthesize myPrivateFoo = _myPrivateFoo;

-(void)doSomeThingWithThisNumber:(NSInteger)aNumber
{
    _myPrivateFoo = aNumber;
}

@end
0

Kommentare

lenn1
lenn124.11.1100:41
Die Lösung ist , dass ich

@interface FooBar()
@property NSInteger myPrivateFoo;
@end

in die Vererbte Klassenimplentierung einfügen muss...

0
Marcel Bresink24.11.1109:04
Ich habe nun aber ein Problem mit der Vererbung dieser.
Ich habe nämlich überhaupt keinen Zugriff auf private Propertys.

Genau das ist ja der Sinn von privaten Bezeichnern. In Unterklassen sind sie nicht zugreifbar. Wenn Du diese Eigenschaft haben willst, musst Du den Bezeichner als @protected deklarieren.
0
Marcel Bresink24.11.1109:25
Beim nochmaligen Durchlesen Deiner Frage ist mir aufgefallen, dass möglicherweise die Begrifflichkeiten etwas durcheinandergehen.

"Private Methoden" gibt es in Objective-C überhaupt nicht (man kann so etwas ähnliches aber mit Kategorien erreichen) und der Begriff "private Property" ist eigentlich ein Widerspruch in sich. Das Ziel einer Property ist ja gerade, sie von außen zugreifbar zu machen, also das Gegenteil von privat.
0
MacMark
MacMark24.11.1111:01
Was er für "private" hält, ist, mit einer anonymen Category die Variable zu verstecken. Verstecken verhindert aber nicht jede Art des Zugriffs. Das macht man außerdem eher mit @private. Diese Art des Versteckens via anonyme Category wird normalerweise für Methoden genutzt.

Objective-C ist eine wesentlich dynamischere Sprache als beispielsweise Java. Private Methoden ergeben daher hier wenig Sinn. Man kann die Sichtbarkeit verringern, aber nie jede Form des Zugriffs zur Laufzeit verhindern.

Vererbung wird bei Objective-C weniger eingesetzt. Statt dessen massiv Delegates. Das ergibt eine losere Kopplung.

Die Nutzung des _-Präfixes ist für Apple reserviert. Du könntest damit versehentlich Sachen überschreiben.
„@macmark_de“
0
lenn1
lenn124.11.1111:23
Mag alles richtig sein, was ihr sagt.
Ihr habt da sicherlich mehr Erfahrung.

Nur ist es nunmal Fakt, dass sich seit dem letzten iTunesU CS193P Tutorium grundlegende Dinge geändert haben.

Ich habe es genau so aufgeschrieben wie der Herr in den Videos.

Schlechtes Bild, aber man sollte soviel erkennen, dass er das Property dort oben so deklariert, wie ich es beschrieben habe.
Und das tut er in allen Videos mit Propertys die nach Aussen hin nicht gebraucht werden. Genau wie mit den Unterstrichen. Er erklärt sogar, dass es eine gute Konvention und gängige ist das so zu machen.

Wenn der "Appletyp" auf dem offiziellen "Apple Tutorium" im "Apple iTunesU" das so macht muss da doch irgendwie was dran sein?

Gruß
vom verwirrten lenn1
0
lenn1
lenn124.11.1111:24
Xcode bietet mir sogar an, dass sobald ich einen Unterstrich mache hinter dem Gleichzeichen es _myPrivateInt zu nennen.

0
MacMark
MacMark24.11.1111:25
Dann mach keinen Unterstrich. Xcode wird auch von Apple selbst verwendet, daher dieses Feature. Normalerweise reicht "@synthesize myPrivateFoo" völlig aus. Warum willst Du die Variable anders nennen als den Accessor?
„@macmark_de“
0
Marcel Bresink24.11.1111:26
Auweia, das hatte ich befürchtet. Die runden Klammern hinter FooBar waren also tatsächlich ernst gemeint und kein Tippfehler.

Durch diese Interpretation des Wortes "private" ergibt zwar die Frage mehr Sinn, aber einen solchen "Missbrauch" von Objective-C-Konstrukten als "gängige Konvention" zu bezeichnen, ist schon etwas weit hergeholt.
0
Duck Dodgers24.11.1111:33
lenn1
@interface FooBar()
@property NSInteger myPrivateFoo;
@end
Du brauchst da nichts zu vererben. Das hat schon so seinen Sinn, dass du nicht direkt darauf zugreifen kannst und das empfiehlt auch Apple. Properties werden doch über die accessor methods und nicht direkt gelesen/geschrieben!
Don’t use the underscore character as a prefix for your private methods. Apple reserves this convention.
0
Duck Dodgers24.11.1111:35
MacMark
Dann mach keinen Unterstrich. Xcode wird auch von Apple selbst verwendet, daher dieses Feature. Normalerweise reicht "@synthesize myPrivateFoo" völlig aus. Warum willst Du die Variable anders nennen als den Accessor?

Lau der Doku gilt das nur für private Methoden! Siehe mein Post vorher.
0
MacMark
MacMark24.11.1111:45
Apple reserviert alle Namen, die mit einem einzelnem Underscore beginnen, für sich. Sie nennen auch Variablen so. Wenn man also gern ein paar ungewollte Seiteneffekte riskieren möchte …
„@macmark_de“
0
lenn1
lenn124.11.1111:48
Ich kann auch einfach bei dem bleiben was ich kenne:
In der Header Dateien massig globale Variablen anlegen und nur für diejenigen @propertys anlegen, die auch nach außen hin veränderbar sein sollen.
Vererbung wird bei Objective-C weniger eingesetzt. Statt dessen massiv Delegates. Das ergibt eine losere Kopplung.

Jede Klasse, die ich bisher geschrieben habe erbt irgendetwas von irgendwem.

Ich schildere einfach mal mein Problem.

Ich programmiere gerade ein Spiel, in dem es mehrere Elemente gibt, die ähnlich sind:

AstNormal* - normaler Ast.
VerkohlterAst* - verkohlter Ast.
stachligerAst - Ast mit Dornen.
...



Alle erben von normaler Ast ihre grundlegenden Eigenschaften.
Außerdem gibt es dann im Level eine Methode die alle Äste dem Level hinzufügt.

-(void)addAeste:(AstNormal*)ast1 , ...;

Daher brauche ich das mit der Vererbung zwingend.
Habe schon etliche Methoden geschrieben die als Parameter ein (AstNormal*) haben wollen, aber auch die anderen Äste akzeptieren aufgrund der Vererbung.



Letztendlich besteht ja kein Problem. Ich wollte nur wissen ob ich, da ich noch relativ neu bin, jetzt schon auf dem falschen Wege bin.
0
Marcel Bresink24.11.1111:59
Zu den Unterstrichen: Diese Unsitte findet man leider in vielen Lehrbüchern.

In Klassen, die von vielen fremden Entwicklern genutzt werden sollen (mit anderen Worten: in Systembibliotheken, bzw. -Frameworks), sind Instanzvariablen mit Unterstrich vereinbart, um Namenskollisionen zu vermeiden. Überschreibt man eine solche Klasse, kann man in der Unterklasse gängige Variablennamen (ohne Unterstrich) verwenden, ohne dass man versehentlich auf eine Variable der Oberklasse zugreift. Man muss deren Implementationsdetails nicht kennen.

Für die Praxis heißt das: In eigenen Programmen deklariert man Instanzvariablen immer ohne Unterstrich. Nur in Teilen, in denen Oberklassen für ein unbekanntes Publikum bereitgestellt werden (z.B. in einem Framework oder bei einer Plug-In-Schnittstelle) schützt man Variablen gegen Namenskollisionen. Da Apple inzwischen per Dokumentation den einzelnen Unterstrich für sich selbst beansprucht, sollte man andere Schreibweisen, z.B. nach dem Muster _lenn1_myPrivateFoo oder LENN1_myPrivateFoo verwenden.
0
Marcel Bresink24.11.1112:03
In der Header Dateien massig globale Variablen anlegen und nur für diejenigen @propertys anlegen, die auch nach außen hin veränderbar sein sollen.

Meinst Du wirklich globale Variablen oder Instanzvariablen?
0
lenn1
lenn124.11.1112:04
Ich schau mir das gerade nochmal an, was der Herr Paul Hegarty da von sich gibt.

1. Vorlesung
#import "Spaceship.h"
@interface Spaceship()

// declaration of private Methods (as needed)

@end

@implementation Spaceship
// implementation of public and private Methods
@end


Nur damit ihr was zum aufregen habt
Wie gesagt, der zieht das durchs ganze Tutorium so durch.
Auch das mit den Unterstrichen. Er legt keine einzige Instanzvariable im Headerfile an. Nur @propertys und @synthesize anschliessend.

Gruß
lenn1

Meinst Du wirklich globale Variablen oder Instanzvariablen?
Instanzvariablen natürlich.
0
Marcel Bresink24.11.1112:14
Nur damit ihr was zum aufregen habt

Nein, das was da steht, ist korrekt. Unschön ist nur die Schreibweise "Spaceship()", die leicht überlesen werden kann. Besser wäre so etwas wie "Spaceship(MyPrivateComponents)".

Noch schöner wäre, die beiden Implementationsblöcke voneinander zu trennen, also

@implementation Spaceship
// implementation of public methods
@end

@implementation Spaceship(MyPrivateComponents)
// implementation of private methods
@end

Und man muss sich eben bewusst sein, dass das mehr ein Trick ist, die Sichtbarkeit von Methoden über eine Kategorie einzuschränken. Es hat nichts mit dem offiziellen Sprachkonstrukt @private zu tun.
0
lenn1
lenn124.11.1112:20
"_(underbar) then the name of the property is a common naming convention"

Er erklärt außerdem, dass man nie auf instanzvariablen direkt zugreifen sollte. Nur über Setter & Getter.

"Außer wenn man auf Performance Wert legt, also 1000x pro Sekunde eine Variable ändern oder sowas" - Sinngemäß.

0
lenn1
lenn124.11.1112:28
Naja ihr habt mir schon sehr geholfen.
Denke ich muss dem ganzen ein wenig kritischer gegenüber stehen, was iTunesU da zu bieten hat.

Muss allerdings sagen, dass meine Software mit beiden "Philosophien" funktioniert.Die , die ich bisher angewendet habe ist nur irgendwie ein wenig schöner als die von Herrn Hegarty.

Danke an Alle.

Gruß
lenn1
0
Marcel Bresink24.11.1112:32
Er legt keine einzige Instanzvariable im Headerfile an. Nur @propertys und @synthesize anschliessend.

Für reine iOS-Programmierung ist das zulässig.

Für allgemeine Objective-C-Programmierung ist das schlechte Praxis. Diese Schreibweise ist mit dem klassischen Objective-C-Laufzeitsystem nicht kompatibel. Du bekommst z.B. Schwierigkeiten, wenn Dein Code unter Mac OS X 10.6.8 auf Intel Core Duo-Macs laufen soll.
0
Duck Dodgers24.11.1112:37
@lenn1:
Du zitierst doch selbst aus dem Tutorial, dass du nicht direkt darauf zugreifen sollst. Sorry, aber warum willst du dann deine Properties "vererben"?
MacMark
Apple reserviert alle Namen, die mit einem einzelnem Underscore beginnen, für sich. Sie nennen auch Variablen so. Wenn man also gern ein paar ungewollte Seiteneffekte riskieren möchte …
Steht wo? Das kann doch jeder halten wie er will ... hilft dem Problem hier aber nicht weiter.
0
lenn1
lenn124.11.1112:48
Du zitierst doch selbst aus dem Tutorial, dass du nicht direkt darauf zugreifen sollst. Sorry, aber warum willst du dann deine Properties "vererben"?

Es funktioniert aber auch über die Getter/setter dann nicht, wie ich im 1. Post schon schrieb.
0
MacMark
MacMark24.11.1113:07
lenn1
…Wie gesagt, der zieht das durchs ganze Tutorium so durch.
Auch das mit den Unterstrichen. Er legt keine einzige Instanzvariable im Headerfile an. Nur @propertys und @synthesize anschliessend.

Das mit den Unterstrichen sieht man oft in Apples Beispielcode. Sie ändern das meist nicht für Demos und Beispiele. Daher läuft man Gefahr mit Apples Code zu kollidieren, wenn man seine Variablen ebenfalls so nennt.

Die Instanzvariablen werden durch die @property/@synthesize-Deklarationen passend angelegt ohne daß man sie explizit deklarieren muß. Ist ein Objective-C 2.0-Feature der Modern Runtime auf x86_64 und ARM, wobei der Compiler die passende Instanzvariable einfügt. Wenn Deine Zielplattform das nicht kann, meckert der Compiler.
lenn1
Es funktioniert aber auch über die Getter/setter dann nicht, wie ich im 1. Post schon schrieb.
Auf Objective-C gibt es zwar @private-Variablen, aber richtig privat sind sie nicht, weil man über Tricks doch darauf zugreifen kann. Und private (Accessor- und andere) Methoden gibt es hier nicht. Daher: Laß das mit dem Verstecken der Accessor-Methoden/properties mit Hilfe von anonymen Kategorien lieber bleiben, denn es bringt nichts außer unnötigen Ärger.
„@macmark_de“
0
Duck Dodgers24.11.1114:00
lenn1
Es funktioniert aber auch über die Getter/setter dann nicht, wie ich im 1. Post schon schrieb.
Wie rufst du den die Methode auf? Mit doSomeThingWithThisNumber()? Poste bitte mal den Codeteil.
0
lenn1
lenn124.11.1114:40
Laß das mit dem Verstecken der Accessor-Methoden/properties mit Hilfe von anonymen Kategorien lieber bleiben, denn es bringt nichts außer unnötigen Ärger.

Ja, ich werde es jetzt so machen wie ich es immer gemacht habe. Bin eh der einzige Entwickler der sich das anschaut.

Duck Dodgers

Wie rufst du den die Methode auf? Mit doSomeThingWithThisNumber()? Poste bitte mal den Codeteil.
Wir reden aneinander vorbei denke ich.
Es geht überhaupt nicht um diese Methode.
Die Methode lässt sich nach wie vor ganz normal mit
[self doSomeThingWithThisNumber]
aufrufen, da sie auch im Headerfile deklariert wird.

Was sich beim vererben nichtmehr aufrufen lässt ist der Setter/Getter, den ich in der Kategorie deklariert habe.
bzw. die Instanzvariable direkt.



Du brauchst jetzt aber auch nicht weiter spekulieren. Ich habe alle Antworten bekommen und mittlerweile auch begriffen was der unterschied zwischen private und protected ist.

Wenn ich die Kategorie mit @private vergleiche ist ihr Verhalten ja richtig. Was ich gesucht habe war @protected - was ja auch standard ist.
0

Kommentieren

Diese Diskussion ist bereits mehr als 3 Monate alt und kann daher nicht mehr kommentiert werden.