В проекте я в настоящее время продолжаю работать, существует ряд объектов пользовательского интерфейса различных ароматов и редактора к блоку эти объекты создать страницы для использования в главном приложении, немного как конструктор форм в DevStudio. Эти объекты существуют в своем собственном блоке, и каждый объект является классом, полученным от UserControl
, и имеет пользовательский атрибут. Этот атрибут определяется как это:
[AttributeUsage (AttributeTargets::Class)]
public ref class ControlDescriptionAttribute : Attribute
{
public:
ControlDescriptionAttribute (String ^name, String ^description) :
_name (name),
_description (description)
{
}
property String ^Name
{
String ^get () { return _name; }
}
property String ^Description
{
String ^get () { return _description; }
}
private:
String
^ _name,
^ _description;
};
и я применяю его к классу как это:
[ControlDescription ("Pie Chart", "Displays a pie chart")]
public ref class PieControl sealed : UserControl
{
// stuff
};
, который является тем, что сказали предыдущие плакаты.
Для использования атрибута редактор имеет Generic::List <Type>
содержащий типы управления. Существует поле списка, от которого пользователь может перетащить и отбросить на страницу для создания экземпляра управления. Для заполнения поля списка я добираюсь ControlDescriptionAttribute
для управления и заполняю запись в списке:
// done for each control type
array <Object ^>
// get all the custom attributes
^attributes = controltype->GetCustomAttributes (true);
Type
// this is the one we're interested in
^attributetype = ECMMainPageDisplay::ControlDescriptionAttribute::typeid;
// iterate over the custom attributes
for each (Object ^attribute in attributes)
{
if (attributetype->IsInstanceOfType (attribute))
{
ECMMainPageDisplay::ControlDescriptionAttribute
^description = safe_cast <ECMMainPageDisplay::ControlDescriptionAttribute ^> (attribute);
// get the name and description and create an entry in the list
ListViewItem
^item = gcnew ListViewItem (description->Name);
item->Tag = controltype->Name;
item->SubItems->Add (description->Description);
mcontrols->Items->Add (item);
break;
}
}
Примечание: вышеупомянутое является C++ / CLI, но не трудно преобразовать в C# (да, я знаю, C++ / CLI является отвращением, но это - то, что я должен работать с:-()
, можно поместить атрибуты на большинство вещей и существует целый диапазон предопределенных атрибутов. Редактор упомянул выше, также ищет пользовательские атрибуты на свойствах, которые описывают свойство и как отредактировать его.
, Как только Вы получаете всю эту мысль, Вы зададитесь вопросом, как Вы когда-либо жили без них.
Перво-наперво: в качестве стилистической заметки, соедините фигурные скобки:
[ Person alloc ]
должно быть
[Person alloc]
Я также замечаю, что вы забываете инициализировать Person, когда выделяете его , вам следует использовать:
Person *p = [[Person alloc] init];
Чтобы почувствовать, как объявлять методы, требуется немного времени. Полезно изучить, как фреймворк называет свои методы. Для вашего конкретного примера, я думаю, вы слишком изобретательны. Вы ищете что-то вроде этого:
Person *john = [[Person alloc] initWithName:@"John"];
Person *kelly = [[Person alloc] initWithName:@"Kelly"];
[john greetPerson:kelly withGreeting:@"Hey babe."];
[kelly greetPerson:john withGreeting:@"Get bent."];
Обратите внимание, что я тоже не использовал заглавные буквы g
в greetPerson
. Это стилистическое соглашение Objective-C.
Не забывайте, что объект имеет собственную идентичность, поэтому вам редко нужно указывать объекту (предназначенному для представления человека), кто он есть, прежде чем он поговорит с кем-то. Когда вы пишете сообщение, оно должно читаться как на английском. Когда вы приводите несколько аргументов - правда, редко - начинайте думать с запятыми:
[john sendEmailToPerson:kelly withSubject:subject body:body attachments:nil];
Видите, как это происходит? И даже это оставляет желать лучшего, я еще не освоил это. Дайте ему время.
Очень полезный документ по этому поводу - это Apple Coding Guidelines for Cocoa .
Также выйдите из ловушки C. Вот как я бы написал всю вашу программу (я представляю кучу концепций, так что не ожидайте, что все это поймете):
#import <Foundation/Foundation.h>
@interface Person : NSObject {
NSString *name;
}
@property (copy) NSString *name;
- (id)init;
- (id)initWithName:(NSString *)nm;
- (void)greetPerson:(Person *)who withGreeting:(NSString *)grt;
@end
@implementation Person
@synthesize name;
- (id)init {
if (self = [super init]) {
name = @"James Bond"; // not necessary, but default
} // values don't hurt.
return self;
}
- (id)initWithName:(NSString *)nm {
if (self = [self init]) {
name = [nm copy];
}
return self;
}
- (void)greetPerson:(Person *)who withGreeting:(NSString *)grt {
NSLog(@"%@ says '%@' to %@", self.name, grt, who.name);
}
- (void)dealloc {
[name release];
[super dealloc];
}
@end
int main(int argc, const char * argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Person *john = [[Person alloc] initWithName:@"John"];
Person *kelly = [[Person alloc] initWithName:@"Kelly"];
[john greetPerson:kelly withGreeting:@"StackOverflow is great, isn't it?"];
[kelly greetPerson:john withGreeting:@"Weren't we supposed to flirt?"];
[john release];
[kelly release];
[pool drain];
return 0;
}
Этот код полностью не протестирован, поэтому, если он работает без сбоев, я получить должное впечатление.
s Руководство по кодированию для Какао .Также выйдите из ловушки C. Вот как я бы написал всю вашу программу (я представляю кучу концепций, так что не ожидайте, что вы все поймете):
#import <Foundation/Foundation.h>
@interface Person : NSObject {
NSString *name;
}
@property (copy) NSString *name;
- (id)init;
- (id)initWithName:(NSString *)nm;
- (void)greetPerson:(Person *)who withGreeting:(NSString *)grt;
@end
@implementation Person
@synthesize name;
- (id)init {
if (self = [super init]) {
name = @"James Bond"; // not necessary, but default
} // values don't hurt.
return self;
}
- (id)initWithName:(NSString *)nm {
if (self = [self init]) {
name = [nm copy];
}
return self;
}
- (void)greetPerson:(Person *)who withGreeting:(NSString *)grt {
NSLog(@"%@ says '%@' to %@", self.name, grt, who.name);
}
- (void)dealloc {
[name release];
[super dealloc];
}
@end
int main(int argc, const char * argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Person *john = [[Person alloc] initWithName:@"John"];
Person *kelly = [[Person alloc] initWithName:@"Kelly"];
[john greetPerson:kelly withGreeting:@"StackOverflow is great, isn't it?"];
[kelly greetPerson:john withGreeting:@"Weren't we supposed to flirt?"];
[john release];
[kelly release];
[pool drain];
return 0;
}
Этот код полностью не протестирован, поэтому, если он работает без сбоев, я получить должное впечатление.
s Руководство по кодированию для Какао .Также выйдите из ловушки C. Вот как я бы написал всю вашу программу (я представляю кучу концепций, так что не ожидайте, что все это поймете):
#import <Foundation/Foundation.h>
@interface Person : NSObject {
NSString *name;
}
@property (copy) NSString *name;
- (id)init;
- (id)initWithName:(NSString *)nm;
- (void)greetPerson:(Person *)who withGreeting:(NSString *)grt;
@end
@implementation Person
@synthesize name;
- (id)init {
if (self = [super init]) {
name = @"James Bond"; // not necessary, but default
} // values don't hurt.
return self;
}
- (id)initWithName:(NSString *)nm {
if (self = [self init]) {
name = [nm copy];
}
return self;
}
- (void)greetPerson:(Person *)who withGreeting:(NSString *)grt {
NSLog(@"%@ says '%@' to %@", self.name, grt, who.name);
}
- (void)dealloc {
[name release];
[super dealloc];
}
@end
int main(int argc, const char * argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Person *john = [[Person alloc] initWithName:@"John"];
Person *kelly = [[Person alloc] initWithName:@"Kelly"];
[john greetPerson:kelly withGreeting:@"StackOverflow is great, isn't it?"];
[kelly greetPerson:john withGreeting:@"Weren't we supposed to flirt?"];
[john release];
[kelly release];
[pool drain];
return 0;
}
Этот код полностью не протестирован, поэтому, если он работает без сбоев, я получить должное впечатление.
Другие люди затронули самые важные моменты, поэтому я просто взвешу некоторые дополнительные вопросы:
Также меня что-то беспокоит, и это имя первого параметра - в основном то же самое, что и название «сообщения». Как решить эту проблему при написании значимых и понятных методов / «имен сообщений»?
Наиболее распространенный способ решения этой проблемы - сделать имя метода комбинацией «что он / делает» и метки для первого параметр. Пример:
NSColor * color = [NSColor colorWithDeviceRed:0.5 green:0.5 blue:0.5 alpha:0.5];
Может ли кто-нибудь объяснить причину появления двух имен для каждого параметра и, возможно, более полезный пример того, как это можно эффективно использовать для придания значения программе?
Быстрый ответ состоит в том, что эти два имени предназначены для разные аудитории; один предназначен для пользователя метода, второй - автору метода. Снова рассмотрим приведенный выше пример. Объявление метода выглядит так:
+ (NSColor *)colorWithDeviceRed:(CGFloat)red
green:(CGFloat)green
blue:(CGFloat)blue
alpha:(CGFloat)alpha
Когда пользователь вызывает этот метод, его интересуют первые метки (те, которые стоят перед двоеточием). В моем первом примере, где значения каналов передаются как числовые константы, в коде видны только метки.
Фактические имена параметров (части после типа) используются внутри ] определение метода, и как таковые существуют только для программиста, который пишет метод, поскольку это переменные, которые будут доступны в самом теле метода.
Первой «частью» метода является селектор
, в вашем примере он включает -greet: toPerson: greetWith:
, это фактическое имя метода.
Вторая «часть» - это параметры метода, в вашем примере они предназначены для приветствия.
Это похоже на что-то вроде C, где у вас было бы
int greet(string to, string greeting) {
print(greeting, to);
}
Я также должен упомяните, вы, вероятно, захотите работать с NSString *
вместо char *
и NSLog ()
вместо printf ()
(не волнуйтесь, работает почти так же).
Вероятно, это было бы так:
[personJohn greetPerson:@"Kelly" withGreeting:@"hey babe"];
Объект person уже является Джоном, и он приветствует объект другого человека, который я бы не определил как строку, как вы, а вместо этого как другой экземпляр класса Person, а затем вы можете выполнить greetWithString
.
[personJohn greetPerson:personKelly withGreeting:@"hey babe"];
Вы не определяете параметры дважды, вот где вы запутались. Если вы знаете C ++, у вас обычно есть:
void greetPerson(Person thePerson, string greeting);
в качестве, например, прототипа функции. Тогда вы бы назвали это так:
greetPerson(personKelly, "hey babe");
Все, что делает objective-c, облегчает вам задачу, будучи самодокументированным. Вместо того, чтобы просто помещать параметры в функции, вы называете их перед тем, как указывать их, поэтому приведенный выше вызов будет:
greetPerson(Person:personKelly, greeting:"hey babe");
с учетом прототипа функции, опубликованного выше. Таким образом, когда вы читаете код, вы знаете, что делает каждый параметр, следовательно, вы сами документируете.
Имя описанного выше метода - «Greet: toPerson: greetWith:». Двоеточие являются частью имени. Параметры (и их спецификаторы типа) - нет.
Примечание по стилю: не начинайте имя метода с символа верхнего регистра, если вы не ссылаетесь на аббревиатуру (например, «URL»).