diff --git a/Foundation/CPArray.j b/Foundation/CPArray.j index 866fd8dad..4134df19f 100755 --- a/Foundation/CPArray.j +++ b/Foundation/CPArray.j @@ -108,7 +108,9 @@ CPEnumerationReverse = 1 << 1; */ + (id)alloc { - return []; + var result = []; + result.isa = [self class]; + return result; } /*! diff --git a/Foundation/CPData.j b/Foundation/CPData.j index 0a75abd36..8e8c20340 100644 --- a/Foundation/CPData.j +++ b/Foundation/CPData.j @@ -36,7 +36,9 @@ + (id)alloc { - return new CFMutableData(); + result = new CFMutableData(); + result.isa = [self class]; + return result; } + (CPData)data diff --git a/Foundation/CPDate.j b/Foundation/CPDate.j index 3ecdd21a4..f04b3849b 100644 --- a/Foundation/CPDate.j +++ b/Foundation/CPDate.j @@ -39,7 +39,9 @@ var CPDateReferenceDate = new Date(Date.UTC(2001, 1, 1, 0, 0, 0, 0)); + (id)alloc { - return new Date; + var result = new Date; + result.isa = [self class]; + return result; } + (id)date diff --git a/Foundation/CPDictionary.j b/Foundation/CPDictionary.j index 61634cd67..3d42951c2 100755 --- a/Foundation/CPDictionary.j +++ b/Foundation/CPDictionary.j @@ -84,7 +84,9 @@ */ + (id)alloc { - return new CFMutableDictionary(); + var result = new CFMutableDictionary(); + result.isa = [self class]; + return result; } /*! diff --git a/Foundation/CPException.j b/Foundation/CPException.j index 770c6ad63..7a9c8c959 100755 --- a/Foundation/CPException.j +++ b/Foundation/CPException.j @@ -54,6 +54,7 @@ if (input == nil) */ + (id)alloc { + if ([self class] !== CPException) return [super alloc]; return new Error(); } diff --git a/Foundation/CPNumber.j b/Foundation/CPNumber.j index a0bbef39e..a65949a88 100644 --- a/Foundation/CPNumber.j +++ b/Foundation/CPNumber.j @@ -43,7 +43,9 @@ var __placeholder = new Number(), + (id)alloc { - return __placeholder; + var result = new Number(); + result.isa = [self class]; + return result; } + (id)numberWithBool:(BOOL)aBoolean diff --git a/Foundation/CPString.j b/Foundation/CPString.j index 547294939..c6a0d29d3 100644 --- a/Foundation/CPString.j +++ b/Foundation/CPString.j @@ -91,6 +91,7 @@ var CPStringRegexSpecialCharacters = [ */ + (id)alloc { + if ([self class] !== CPString) return [super alloc]; return new String; } @@ -134,7 +135,14 @@ var CPStringRegexSpecialCharacters = [ */ - (id)initWithString:(CPString)aString { - return String(aString); + if ([self class] === CPString) + return String(aString); + + var result = new String(aString); + + result.isa = [self class]; + + return result; } /*! diff --git a/Foundation/CPURL.j b/Foundation/CPURL.j index 1486baad3..a79e1aae4 100644 --- a/Foundation/CPURL.j +++ b/Foundation/CPURL.j @@ -54,7 +54,9 @@ CPURLCustomIconKey = @"CPURLCustomIconKey"; + (id)alloc { - return new CFURL(); + var result = new CFURL(); + result.isa = [self class]; + return result; } - (id)init @@ -81,7 +83,9 @@ CPURLCustomIconKey = @"CPURLCustomIconKey"; - (id)initWithString:(CPString)URLString relativeToURL:(CPURL)aBaseURL { - return new CFURL(URLString, aBaseURL); + var result = new CFURL(URLString, aBaseURL); + result.isa = [self class]; + return result; } + (id)URLWithString:(CPString)URLString relativeToURL:(CPURL)aBaseURL diff --git a/Tests/Foundation/SubclassTollFreeTest.j b/Tests/Foundation/SubclassTollFreeTest.j new file mode 100644 index 000000000..f7b6191b5 --- /dev/null +++ b/Tests/Foundation/SubclassTollFreeTest.j @@ -0,0 +1,138 @@ +@implementation SubclassTollFreeTest : OJTestCase + +- (void)testThatSubclassTollFreeDoesAllowForSubclassingDictionary +{ + var target = [[MyDict alloc] init]; + [OJAssert assert:@"a" equals:[target newMessage]]; + [OJAssert assert:0 equals:[target count]]; +} + +- (void)testThatSubclassTollFreeDoesAllowForSubclassingString +{ + var target = [[MyString alloc] initWithString:@"adsf"]; + [OJAssert assert:@"a" equals:[target newMessage]]; + [OJAssert assert:4 equals:[target length]]; + + var target2 = "agdsa"; + [OJAssert assertThrows:function(){ [target2 newMessage]; }]; + [OJAssert assert:5 equals:[target2 length]]; +} + +- (void)testThatSubclassTollFreeDoesAllowForSubclassingNumber +{ + var target = [[MyNum alloc] init]; + [OJAssert assert:@"a" equals:[target newMessage]]; + [OJAssert assertFalse:[target isEqualToNumber:5]]; +} + +- (void)testThatSubclassTollFreeDoesAllowForSubclassingException +{ + var target = [[MyException alloc] init]; + [OJAssert assert:@"a" equals:[target newMessage]]; + // there are no internal properties to test here.. so no need to jimmyrig it. +} + +- (void)testThatSubclassTollFreeDoesAllowForSubclassingArray +{ + var target = [[MyArray alloc] initWithObjects:@"a"]; + [OJAssert assert:@"a" equals:[target newMessage]]; + [OJAssert assert:1 equals:[target count]]; +} + +- (void)testThatSubclassTollFreeDoesAllowForSubclassingDate +{ + var target = [[MyDate alloc] init]; + [OJAssert assert:@"a" equals:[target newMessage]]; + [OJAssert assertTrue:[target timeIntervalSince1970] > 0]; +} + +- (void)testThatSubclassTollFreeDoesAllowForSubclassingData +{ + var target = [[MyData alloc] initWithRawString:@"b"]; + [OJAssert assert:@"a" equals:[target newMessage]]; + [OJAssert assert:@"b" equals:[target rawString]]; +} + +- (void)testThatSubclassTollFreeDoesAllowForSubclassingURL +{ + var target = [[MyURL alloc] initWithString:@"http://www.google.com"]; + [OJAssert assert:@"a" equals:[target newMessage]]; + [OJAssert assert:@"http://www.google.com" equals:[target absoluteString]]; +} + + +@end + +@import + +@implementation MyDict : CPDictionary + +- (id)newMessage +{ + return "a"; +} + +@end + +@implementation MyNum : CPNumber + +- (id)newMessage +{ + return "a"; +} + +@end + +@implementation MyString : CPString + +- (id)newMessage +{ + return "a"; +} + +@end + +@implementation MyException : CPException + +- (id)newMessage +{ + return "a"; +} + +@end + +@implementation MyArray : CPArray + +- (id)newMessage +{ + return "a"; +} + +@end + +@implementation MyDate : CPDate + +- (id)newMessage +{ + return "a"; +} + +@end + +@implementation MyData : CPData + +- (id)newMessage +{ + return "a"; +} + +@end + +@implementation MyURL : CPURL + +- (id)newMessage +{ + return "a"; +} + +@end