Objective-C代码学习大纲(4)

2011-05-11 14:06 佚名 otierney 字号:T | T

本文为台湾出版的《Objective-C学习大纲》的翻译文档,系统介绍了Objective-C代码,很多名词为台湾同胞特指词汇,在学习时仔细研读才能体会。

AD:干货来了,不要等!WOT2015 北京站演讲PPT开放下载!

继承、多型(Inheritance, Polymorphism)以及其他物件导向功能

id 型别

Objective-C 有种叫做 id 的型别,它的运作有时候像是 void*,不过它却严格规定只能用在物件。Objective-C 与 Java 跟 C++ 不一样,你在唿叫一个物件的 method 时,并不需要知道这个物件的型别。当然这个 method 一定要存在,这称为 Objective-C 的讯息传递。

  1. Fraction.h
  2. #import
  3. @interface Fraction: NSObject {
  4. int numerator;
  5. int denominator;
  6. }
  7. -(Fraction*) initWithNumerator: (int) n denominator: (int) d;
  8. -(void) print;
  9. -(void) setNumerator: (int) d;
  10. -(void) setDenominator: (int) d;
  11. -(void) setNumerator: (int) n andDenominator: (int) d;
  12. -(int) numerator;
  13. -(int) denominator;
  14. @end
  15. Fraction.m
  16. #import "Fraction.h"
  17. #import
  18. @implementation Fraction
  19. -(Fraction*) initWithNumerator: (int) n denominator: (int) d {
  20. self = [super init];
  21. if ( self ) {
  22. [self setNumerator: n andDenominator: d];
  23. }
  24. return self;
  25. }
  26. -(void) print {
  27. printf( "%i / %i", numerator, denominator );
  28. }
  29. -(void) setNumerator: (int) n {
  30. nnumerator = n;
  31. }
  32. -(void) setDenominator: (int) d {
  33. ddenominator = d;
  34. }
  35. -(void) setNumerator: (int) n andDenominator: (int) d {
  36. nnumerator = n;
  37. ddenominator = d;
  38. }
  39. -(int) denominator {
  40. return denominator;
  41. }
  42. -(int) numerator {
  43. return numerator;
  44. }
  45. @end
  46. Complex.h
  47. #import
  48. @interface Complex: NSObject {
  49. double real;
  50. double imaginary;
  51. }
  52. -(Complex*) initWithReal: (double) r andImaginary: (double) i;
  53. -(void) setReal: (double) r;
  54. -(void) setImaginary: (double) i;
  55. -(void) setReal: (double) r andImaginary: (double) i;
  56. -(double) real;
  57. -(double) imaginary;
  58. -(void) print;
  59. @end
  60. Complex.m
  61. #import "Complex.h"
  62. #import
  63. @implementation Complex
  64. -(Complex*) initWithReal: (double) r andImaginary: (double) i {
  65. self = [super init];
  66. if ( self ) {
  67. [self setReal: r andImaginary: i];
  68. }
  69. return self;
  70. }
  71. -(void) setReal: (double) r {
  72. rreal = r;
  73. }
  74. -(void) setImaginary: (double) i {
  75. iimaginary = i;
  76. }
  77. -(void) setReal: (double) r andImaginary: (double) i {
  78. rreal = r;
  79. iimaginary = i;
  80. }
  81. -(double) real {
  82. return real;
  83. }
  84. -(double) imaginary {
  85. return imaginary;
  86. }
  87. -(void) print {
  88. printf( "%_f + %_fi", real, imaginary );
  89. }
  90. @end
  91. main.m
  92. #import
  93. #import "Fraction.h"
  94. #import "Complex.h"
  95. int main( int argc, const char *argv[] ) {
  96. // create a new instance
  97. Fraction *frac = [[Fraction alloc] initWithNumerator: 1 denominator: 10];
  98. Complex *comp = [[Complex alloc] initWithReal: 10 andImaginary: 15];
  99. id number;
  100. // print fraction
  101. number = frac;
  102. printf( "The fraction is: " );
  103. [number print];
  104. printf( "\n" );
  105. // print complex
  106. number = comp;
  107. printf( "The complex number is: " );
  108. [number print];
  109. printf( "\n" );
  110. // free memory
  111. [frac release];
  112. [comp release];
  113. return 0;
  114. }

output

  1. The fraction is: 1 / 10
  2. The complex number is: 10.000000 + 15.000000i

这种动态连结有显而易见的好处。你不需要知道你唿叫 method 的那个东西是什么型别,如果这个物件对这个讯息有反应,那就会唤起这个 method。这也不会牵涉到一堆繁琐的转型动作,比如在 Java 裡唿叫一个整数物件的 .intValue() 就得先转型,然后才能唿叫这个 method。

继承(Inheritance)

  1. Rectangle.h
  2. #import
  3. @interface Rectangle: NSObject {
  4. int width;
  5. int height;
  6. }
  7. -(Rectangle*) initWithWidth: (int) w height: (int) h;
  8. -(void) setWidth: (int) w;
  9. -(void) setHeight: (int) h;
  10. -(void) setWidth: (int) w height: (int) h;
  11. -(int) width;
  12. -(int) height;
  13. -(void) print;
  14. @end
  15. Rectangle.m
  16. #import "Rectangle.h"
  17. #import
  18. @implementation Rectangle
  19. -(Rectangle*) initWithWidth: (int) w height: (int) h {
  20. self = [super init];
  21. if ( self ) {
  22. [self setWidth: w height: h];
  23. }
  24. return self;
  25. }
  26. -(void) setWidth: (int) w {
  27. wwidth = w;
  28. }
  29. -(void) setHeight: (int) h {
  30. hheight = h;
  31. }
  32. -(void) setWidth: (int) w height: (int) h {
  33. wwidth = w;
  34. hheight = h;
  35. }
  36. -(int) width {
  37. return width;
  38. }
  39. -(int) height {
  40. return height;
  41. }
  42. -(void) print {
  43. printf( "width = %i, height = %i", width, height );
  44. }
  45. @end
  46. Square.h
  47. #import "Rectangle.h"
  48. @interface Square: Rectangle
  49. -(Square*) initWithSize: (int) s;
  50. -(void) setSize: (int) s;
  51. -(int) size;
  52. @end
  53. Square.m
  54. #import "Square.h"
  55. @implementation Square
  56. -(Square*) initWithSize: (int) s {
  57. self = [super init];
  58. if ( self ) {
  59. [self setSize: s];
  60. }
  61. return self;
  62. }
  63. -(void) setSize: (int) s {
  64. width = s;
  65. height = s;
  66. }
  67. -(int) size {
  68. return width;
  69. }
  70. -(void) setWidth: (int) w {
  71. [self setSize: w];
  72. }
  73. -(void) setHeight: (int) h {
  74. [self setSize: h];
  75. }
  76. @end
  77. main.m
  78. #import "Square.h"
  79. #import "Rectangle.h"
  80. #import
  81. int main( int argc, const char *argv[] ) {
  82. Rectangle *rec = [[Rectangle alloc] initWithWidth: 10 height: 20];
  83. Square *sq = [[Square alloc] initWithSize: 15];
  84. // print em
  85. printf( "Rectangle: " );
  86. [rec print];
  87. printf( "\n" );
  88. printf( "Square: " );
  89. [sq print];
  90. printf( "\n" );
  91. // update square
  92. [sq setWidth: 20];
  93. printf( "Square after change: " );
  94. [sq print];
  95. printf( "\n" );
  96. // free memory
  97. [rec release];
  98. [sq release];
  99. return 0;
  100. }

output

  1. Rectangle: width = 10, height = 20
  2. Square: width = 15, height = 15
  3. Square after change: width = 20, height = 20

继承在 Objective-C 裡比较像 Java。当你扩充你的 super class(所以只能有一个 parent),你想自订这个 super class 的 method,只要简单的在你的 child class implementation 裡放上新的实作内容即可。而不需要 C++ 裡呆呆的 virtual table。

这裡还有一个值得玩味的地方,如果你企图像这样去唿叫 rectangle 的 constructor: Square *sq = [[Square alloc] initWithWidth: 10 height: 15],会发生什么事?答案是会产生一个编译器错误。因为 rectangle constructor 回传的型别是 Rectangle*,而不是 Square*,所以这行不通。在某种情况下如果你真想这样用,使用 id 型别会是很好的选择。如果你想使用 parent 的 constructor,只要把 Rectangle* 回传型别改成 id 即可。

动态识别(Dynamic types)

这裡有一些用于 Objective-C 动态识别的 methods(说明部分採中英并列,因为我觉得英文比较传神,中文怎么译都怪):

  1. -(BOOL) isKindOfClass: classObjis object a descendent or member of classObj

此物件是否是 classObj 的子孙或一员

  1. -(BOOL) isMemberOfClass: classObjis object a member of classObj

此物件是否是 classObj 的一员

  1. -(BOOL) respondsToSelector: selectordoes the object have a method named specifiec by the selector

此物件是否有叫做 selector 的 method

  1. +(BOOL) instancesRespondToSelector: selectordoes an object created by this class have the ability to respond to the specified selector

此物件是否是由有能力回应指定 selector 的物件所产生

  1. -(id) performSelector: selectorinvoke the specified selector on the object

唤起此物件的指定 selector

所有继承自 NSObject 都有一个可回传一个 class 物件的 class method。这非常近似于 Java 的 getClass() method。这个 class 物件被使用于前述的 methods 中。

Selectors 在 Objective-C 用以表示讯息。下一个範例会秀出建立 selector 的语法。

  1. main.m
  2. #import "Square.h"
  3. #import "Rectangle.h"
  4. #import
  5. int main( int argc, const char *argv[] ) {
  6. Rectangle *rec = [[Rectangle alloc] initWithWidth: 10 height: 20];
  7. Square *sq = [[Square alloc] initWithSize: 15];
  8. // isMemberOfClass
  9. // true
  10. if ( [sq isMemberOfClass: [Square class]] == YES ) {
  11. printf( "square is a member of square class\n" );
  12. }
  13. // false
  14. if ( [sq isMemberOfClass: [Rectangle class]] == YES ) {
  15. printf( "square is a member of rectangle class\n" );
  16. }
  17. // false
  18. if ( [sq isMemberOfClass: [NSObject class]] == YES ) {
  19. printf( "square is a member of object class\n" );
  20. }
  21. // isKindOfClass
  22. // true
  23. if ( [sq isKindOfClass: [Square class]] == YES ) {
  24. printf( "square is a kind of square class\n" );
  25. }
  26. // true
  27. if ( [sq isKindOfClass: [Rectangle class]] == YES ) {
  28. printf( "square is a kind of rectangle class\n" );
  29. }
  30. // true
  31. if ( [sq isKindOfClass: [NSObject class]] == YES ) {
  32. printf( "square is a kind of object class\n" );
  33. }
  34. // respondsToSelector
  35. // true
  36. if ( [sq respondsToSelector: @selector( setSize: )] == YES ) {
  37. printf( "square responds to setSize: method\n" );
  38. }
  39. // false
  40. if ( [sq respondsToSelector: @selector( nonExistant )] == YES ) {
  41. printf( "square responds to nonExistant method\n" );
  42. }
  43. // true
  44. if ( [Square respondsToSelector: @selector( alloc )] == YES ) {
  45. printf( "square class responds to alloc method\n" );
  46. }
  47. // instancesRespondToSelector
  48. // false
  49. if ( [Rectangle instancesRespondToSelector: @selector( setSize: )] == YES ) {
  50. printf( "rectangle instance responds to setSize: method\n" );
  51. }
  52. // true
  53. if ( [Square instancesRespondToSelector: @selector( setSize: )] == YES ) {
  54. printf( "square instance responds to setSize: method\n" );
  55. }
  56. // free memory
  57. [rec release];
  58. [sq release];
  59. return 0;
  60. }

output

  1. square is a member of square class
  2. square is a kind of square class
  3. square is a kind of rectangle class
  4. square is a kind of object class
  5. square responds to setSize: method
  6. square class responds to alloc method
  7. square instance responds to setSize: method
  8. Categories

当你想要为某个 class 新增 methods,你通常会扩充(extend,即继承)它。然而这不一定是个完美解法,特别是你想要重写一个 class 的某个功能,但你却没有塬始码时。Categories 允许你在现有的 class 加入新功能,但不需要扩充它。Ruby 语言也有类似的功能。

  1. FractionMath.h
  2. #import "Fraction.h"
  3. @interface Fraction (Math)
  4. -(Fraction*) add: (Fraction*) f;
  5. -(Fraction*) mul: (Fraction*) f;
  6. -(Fraction*) div: (Fraction*) f;
  7. -(Fraction*) sub: (Fraction*) f;
  8. @end
  9. FractionMath.m
  10. #import "FractionMath.h"
  11. @implementation Fraction (Math)
  12. -(Fraction*) add: (Fraction*) f {
  13. return [[Fraction alloc] initWithNumerator: numerator * [f denominator] +
  14. denominator * [f numerator]
  15. denominator: denominator * [f denominator]];
  16. }
  17. -(Fraction*) mul: (Fraction*) f {
  18. return [[Fraction alloc] initWithNumerator: numerator * [f numerator]
  19. denominator: denominator * [f denominator]];
  20. }
  21. -(Fraction*) div: (Fraction*) f {
  22. return [[Fraction alloc] initWithNumerator: numerator * [f denominator]
  23. denominator: denominator * [f numerator]];
  24. }
  25. -(Fraction*) sub: (Fraction*) f {
  26. return [[Fraction alloc] initWithNumerator: numerator * [f denominator] -
  27. denominator * [f numerator]
  28. denominator: denominator * [f denominator]];
  29. }
  30. @end
  31. main.m
  32. #import
  33. #import "Fraction.h"
  34. #import "FractionMath.h"
  35. int main( int argc, const char *argv[] ) {
  36. // create a new instance
  37. Fraction *frac1 = [[Fraction alloc] initWithNumerator: 1 denominator: 3];
  38. Fraction *frac2 = [[Fraction alloc] initWithNumerator: 2 denominator: 5];
  39. Fraction *frac3 = [frac1 mul: frac2];
  40. // print it
  41. [frac1 print];
  42. printf( " * " );
  43. [frac2 print];
  44. printf( " = " );
  45. [frac3 print];
  46. printf( "\n" );
  47. // free memory
  48. [frac1 release];
  49. [frac2 release];
  50. [frac3 release];
  51. return 0;
  52. }

output

  1. 1/3 * 2/5 = 2/15

重点是 @implementation 跟 @interface 这两行:@interface Fraction (Math) 以及 @implementation Fraction (Math).

(同一个 class)只能有一个同名的 category,其他的 categories 得加上不同的、独一无二的名字。

Categories 在建立 private methods 时十分有用。因为 Objective-C 并没有像 Java 这种 private/protected/public methods 的概念,所以必须要使用 categories 来达成这种功能。作法是把 private method 从你的 class header (.h) 档案移到 implementation (.m) 档案。以下是此种作法一个简短的範例。

  1. MyClass.h
  2. #import
  3. @interface MyClass: NSObject
  4. -(void) publicMethod;
  5. @end
  6. MyClass.m
  7. #import "MyClass.h"
  8. #import
  9. @implementation MyClass
  10. -(void) publicMethod {
  11. printf( "public method\n" );
  12. }
  13. @end
  14. // private methods
  15. @interface MyClass (Private)
  16. -(void) privateMethod;
  17. @end
  18. @implementation MyClass (Private)
  19. -(void) privateMethod {
  20. printf( "private method\n" );
  21. }
  22. @end
  23. main.m
  24. #import "MyClass.h"
  25. int main( int argc, const char *argv[] ) {
  26. MyClass *obj = [[MyClass alloc] init];
  27. // this compiles
  28. [obj publicMethod];
  29. // this throws errors when compiling
  30. //[obj privateMethod];
  31. // free memory
  32. [obj release];
  33. return 0;
  34. }

output

  1. public method
  2. Posing

Posing 有点像 categories,但是不太一样。它允许你扩充一个 class,并且全面性地的扮演(pose)这个 super class。例如:你有一个扩充 NSArray 的 NSArrayChild 物件。如果你让 NSArrayChild 扮演 NSArray,则在你的程式码中所有的 NSArray 都会自动被替代为 NSArrayChild。

  1. FractionB.h
  2. #import "Fraction.h"
  3. @interface FractionB: Fraction
  4. -(void) print;
  5. @end
  6. FractionB.m
  7. #import "FractionB.h"
  8. #import
  9. @implementation FractionB
  10. -(void) print {
  11. printf( "(%i/%i)", numerator, denominator );
  12. }
  13. @end
  14. main.m
  15. #import
  16. #import "Fraction.h"
  17. #import "FractionB.h"
  18. int main( int argc, const char *argv[] ) {
  19. Fraction *frac = [[Fraction alloc] initWithNumerator: 3 denominator: 10];
  20. // print it
  21. printf( "The fraction is: " );
  22. [frac print];
  23. printf( "\n" );
  24. // make FractionB pose as Fraction
  25. [FractionB poseAsClass: [Fraction class]];
  26. Fraction *frac2 = [[Fraction alloc] initWithNumerator: 3 denominator: 10];
  27. // print it
  28. printf( "The fraction is: " );
  29. [frac2 print];
  30. printf( "\n" );
  31. // free memory
  32. [frac release];
  33. [frac2 release];
  34. return 0;
  35. }

output

  1. The fraction is: 3/10
  2. The fraction is: (3/10)

这个程式的输出中,第一个 fraction 会输出 3/10,而第二个会输出 (3/10)。这是 FractionB 中实作的方式。

poseAsClass 这个 method 是 NSObject 的一部份,它允许 subclass 扮演 superclass。

Protocols

Objective-C 裡的 Protocol 与 Java 的 interface 或是 C++ 的 purely virtual class 相同。

  1. Printing.h
  2. @protocol Printing
  3. -(void) print;
  4. @end
  5. Fraction.h
  6. #import
  7. #import "Printing.h"
  8. @interface Fraction: NSObject {
  9. int numerator;
  10. int denominator;
  11. }
  12. -(Fraction*) initWithNumerator: (int) n denominator: (int) d;
  13. -(void) setNumerator: (int) d;
  14. -(void) setDenominator: (int) d;
  15. -(void) setNumerator: (int) n andDenominator: (int) d;
  16. -(int) numerator;
  17. -(int) denominator;
  18. @end
  19. Fraction.m
  20. #import "Fraction.h"
  21. #import
  22. @implementation Fraction
  23. -(Fraction*) initWithNumerator: (int) n denominator: (int) d {
  24. self = [super init];
  25. if ( self ) {
  26. [self setNumerator: n andDenominator: d];
  27. }
  28. return self;
  29. }
  30. -(void) print {
  31. printf( "%i/%i", numerator, denominator );
  32. }
  33. -(void) setNumerator: (int) n {
  34. nnumerator = n;
  35. }
  36. -(void) setDenominator: (int) d {
  37. ddenominator = d;
  38. }
  39. -(void) setNumerator: (int) n andDenominator: (int) d {
  40. nnumerator = n;
  41. ddenominator = d;
  42. }
  43. -(int) denominator {
  44. return denominator;
  45. }
  46. -(int) numerator {
  47. return numerator;
  48. }
  49. -(Fraction*) copyWithZone: (NSZone*) zone {
  50. return [[Fraction allocWithZone: zone] initWithNumerator: numerator
  51. denominator: denominator];
  52. }
  53. @end
  54. Complex.h
  55. #import
  56. #import "Printing.h"
  57. @interface Complex: NSObject {
  58. double real;
  59. double imaginary;
  60. }
  61. -(Complex*) initWithReal: (double) r andImaginary: (double) i;
  62. -(void) setReal: (double) r;
  63. -(void) setImaginary: (double) i;
  64. -(void) setReal: (double) r andImaginary: (double) i;
  65. -(double) real;
  66. -(double) imaginary;
  67. @end
  68. Complex.m
  69. #import "Complex.h"
  70. #import
  71. @implementation Complex
  72. -(Complex*) initWithReal: (double) r andImaginary: (double) i {
  73. self = [super init];
  74. if ( self ) {
  75. [self setReal: r andImaginary: i];
  76. }
  77. return self;
  78. }
  79. -(void) setReal: (double) r {
  80. rreal = r;
  81. }
  82. -(void) setImaginary: (double) i {
  83. iimaginary = i;
  84. }
  85. -(void) setReal: (double) r andImaginary: (double) i {
  86. rreal = r;
  87. iimaginary = i;
  88. }
  89. -(double) real {
  90. return real;
  91. }
  92. -(double) imaginary {
  93. return imaginary;
  94. }
  95. -(void) print {
  96. printf( "%_f + %_fi", real, imaginary );
  97. }
  98. @end
  99. main.m
  100. #import
  101. #import "Fraction.h"
  102. #import "Complex.h"
  103. int main( int argc, const char *argv[] ) {
  104. // create a new instance
  105. Fraction *frac = [[Fraction alloc] initWithNumerator: 3 denominator: 10];
  106. Complex *comp = [[Complex alloc] initWithReal: 5 andImaginary: 15];
  107. id printable;
  108. id copyPrintable;
  109. // print it
  110. printable = frac;
  111. printf( "The fraction is: " );
  112. [printable print];
  113. printf( "\n" );
  114. // print complex
  115. printable = comp;
  116. printf( "The complex number is: " );
  117. [printable print];
  118. printf( "\n" );
  119. // this compiles because Fraction comforms to both Printing and NSCopyable
  120. copyPrintable = frac;
  121. // this doesn‘t compile because Complex only conforms to Printing
  122. //copyPrintable = comp;
  123. // test conformance
  124. // true
  125. if ( [frac conformsToProtocol: @protocol( NSCopying )] == YES ) {
  126. printf( "Fraction conforms to NSCopying\n" );
  127. }
  128. // false
  129. if ( [comp conformsToProtocol: @protocol( NSCopying )] == YES ) {
  130. printf( "Complex conforms to NSCopying\n" );
  131. }
  132. // free memory
  133. [frac release];
  134. [comp release];
  135. return 0;
  136. }

output

  1. The fraction is: 3/10
  2. The complex number is: 5.000000 + 15.000000i
  3. Fraction conforms to NSCopying

protocol 的宣告十分简单,基本上就是 @protocol ProtocolName (methods you must implement) @end。

要遵从(conform)某个 protocol,将要遵从的 protocols 放在 <> 裡面,并以逗点分隔。如:@interface SomeClass

protocol 要求实作的 methods 不需要放在 header 档裡面的 methods 列表中。如你所见,Complex.h 档案裡没有 -(void) print 的宣告,却还是要实作它,因为它(Complex class)遵从了这个 protocol。

Objective-C 的介面系统有一个独一无二的观念是如何指定一个型别。比起 C++ 或 Java 的指定方式,如:Printing *someVar = ( Printing * ) frac; 你可以使用 id 型别加上 protocol:id var = frac;。这让你可以动态地指定一个要求多个 protocol 的型别,却从头到尾只用了一个变数。如: var = frac;

就像使用@selector 来测试物件的继承关係,你可以使用 @protocol 来测试物件是否遵从介面。如果物件遵从这个介面,[object conformsToProtocol: @protocol( SomeProtocol )] 会回传一个 YES 型态的 BOOL 物件。同样地,对 class 而言也能如法炮製 [SomeClass conformsToProtocol: @protocol( SomeProtocol )]。

时间: 2024-10-19 06:31:38

Objective-C代码学习大纲(4)的相关文章

Objective-C代码学习大纲(1)

2011-05-11 14:06 佚名 otierney 字号:T | T 本文为台湾出版的<Objective-C学习大纲>的翻译文档,系统介绍了Objective-C代码,很多名词为台湾同胞特指词汇,在学习时仔细研读才能体会. AD:干货来了,不要等!WOT2015 北京站演讲PPT开放下载! 所有这篇初学者指南的塬始码都可以由 objc.tar.gz 下载.这篇教学中的许多範例都是由 Steve Kochan 在 Programming in Objective-C. 一书中撰写.如果你

Keras版Faster-RCNN代码学习(IOU,RPN)1

最近开始使用Keras来做深度学习,发现模型搭建相较于MXnet, Caffe等确实比较方便,适合于新手练手,于是找来了目标检测经典的模型Faster-RCNN的keras代码来练练手,代码的主题部分转自知乎专栏Learning Machine,作者张潇捷,链接如下: keras版faster-rcnn算法详解(1.RPN计算) keras版faster-rcnn算法详解 (2.roi计算及其他) 我再对代码中loss的计算,config的设置等细节进行学习 Keras版Faster-RCNN代

一个女大学生的代码学习之路(二)

首先说一下,写这种文章是由于我在四月四日晚上,在手动搭建自己的第一个ssh项目的时候,遇到了一个配置的问题,怎么解决也弄不好,当时是四号晚上九点,我看了一眼表,我就想两个小时之内,我要是能搞定就算行了,但是其实,我搞到三点才OK(凌晨),那时候已经是五号了,转天是一家子去扫墓的时候,结果我居然以这种一个理由没有去,理由是我太累了么?我只是就是搭了一个架子,就是由于我的包太混乱了,导致不兼容,所以tomcat总也不启动,你可能认为好笑,这么简单一个问题怎么就费这多多时间呢,但是作为一个刚接触三框架

导航悬浮于顶部代码学习

导航悬浮于顶部代码学习,由于博客园视频限制,暂时不能全屏观看,如果想全屏观看高清视频,可以点击链接查看:http://www.zymseo.com/20.html jQuery页面滚动顶部悬浮导航是一款带二级下拉菜单的jQuery悬浮导航,导航可跟随页面滚动一直出现在顶部,很实用. 当你使用此效果装饰网页时,出现滚动条无法下拉的情况,是因为悬浮元素加入position:fixed样式之后,已经脱离布局,页面的高度不会把悬浮元素的高度计算在内.比如当前例子,浏览器的可视区域的高度为644px,内容

Android代码学习--点击事件的几种写法

由来:常规的写法参见<写一个apk>,每次点击按钮,按钮先查找文本框等元素,然后再操作,其实查找操作是很费时的操作,因此将该定义放到Activity的onCreate中:Oncreate只会执行一次,这样Activity一旦执行,就先创建好控件们了. 第二种方法:通过匿名内部类的方法:就是button.setOnClickListener(new OnClickListener(){ //实现OnClickListener接口 @Override public void onClick(Vie

Objective C 代码片段(类别)

1 @interface NSString (reverse) 2 3 -(NSString *) reverseString; 4 5 @end 1 @implementation NSString (reverse) 2 3 -(NSString *) reverseString { 4 int length = [self length]; 5 NSMutableString *reversedString; 6 7 reversedString = [[NSMutableString a

公益图书馆-Contribute捐赠-代码学习

1.ContributeController.class.php 控制器 <?php /** * Created by PhpStorm. * User: lxd * Date: 14-7-27 * Time: 下午2:43 */ namespace Home\Controller; class ContributeController extends SyController{ /**@author lxd * @description 首页 */ public function index(

TP框架代码学习 学习记录 3.2.3

文件:think.class.php PHP提供register_shutdown_function()这个函数,能够在脚本终止前回调注册的函数,也就是当 PHP 程序执行完成后执行的函数.register_shutdown_function 执行机制是:PHP把要调用的函数调入内存.当页面所有PHP语句都执行完成时,再调用此 函数.注意,在这个时候从内存中调用,不是从PHP页面中调用,所以上面的例子不能使用相对路径,因为PHP已经当原来的页面不存在了.就没有什么相对路 径可言.注意:regis

Android 开源代码学习——NoBoringActionBar

代码功能 该示例工程实现了自定义ActionBar,可以使一个图片平滑过渡到ActionBar Icon的位置,并以ActionBar Icon的形式展现出来.而且还实现了背景图片的自动切换,缩放和平移.可以在展示用户资料等场景使用. 关键代码学习 2.1 NoBoringActionBarActivity.java setTitleAlpha(clamp(5.0F * ratio - 4.0F, 0.0F, 1.0F)); 注:这行代码是用来设置ActionBar Title 的透明度的,该方