Sự khác biệt giữa các phương thức lớp và thể hiện là gì?


448

Sự khác biệt giữa một phương thức lớp và một phương thức thể hiện là gì?

Các phương thức thể hiện là các hàm truy cập (getters và setters) trong khi các phương thức lớp có khá nhiều thứ khác?

Câu trả lời:


673

Giống như hầu hết các câu trả lời khác đã nói, các phương thức thể hiện sử dụng một thể hiện của một lớp, trong khi một phương thức lớp có thể được sử dụng chỉ với tên lớp. Trong Objective-C, chúng được định nghĩa như vậy:

@interface MyClass : NSObject

+ (void)aClassMethod;
- (void)anInstanceMethod;

@end

Sau đó chúng có thể được sử dụng như vậy:

[MyClass aClassMethod];

MyClass *object = [[MyClass alloc] init];
[object anInstanceMethod];

Một số ví dụ thực tế về các phương thức lớp là các phương thức tiện lợi trên nhiều lớp Foundation như NSString's +stringWithFormat:hoặc NSArray' +arrayWithArray:. Một phương pháp dụ sẽ là NSArray's -countphương pháp.


7
Câu trả lời tốt. Cũng đáng lưu ý rằng bạn sẽ thấy một ký hiệu tốc ký cụ thể để mô tả các phương pháp. Ví dụ: + [NSString chuỗiWithFormat:] là phương thức lớp + stringWithFormat: trên NSString; - [NSArray objectAt Index:] là một phương thức ví dụ. Các phương thức có nhiều phần chọn được viết như - [NSMutableDixi setObject: forKey:] v.v ... Bạn sẽ thường thấy ký hiệu này trong các phản hồi, tài liệu và trong Xcode.
Quinn Taylor

149
Tôi sẽ thêm rằng một phương thức lớp được gọi là phương thức "tĩnh" trong nhiều ngôn ngữ khác. Và để trả lời câu hỏi ban đầu, người truy cập là phương thức cá thể bởi vì họ đang thiết lập và nhận trạng thái của một thể hiện cụ thể. Trong ví dụ trên, số NSArray trả về số lượng đối tượng trong một thể hiện cụ thể.
Brian Pan

2
"trong khi một phương thức lớp có thể được sử dụng chỉ với tên lớp." hoặc đối tượng lớp
user102008

2
Xin lỗi vì sự phấn khích của tôi ... nhưng tôi chỉ học được sự khác biệt và tiềm năng của nó. lớp phương pháp rock và lớp singleton cũng vậy! Tôi đã yêu! <3
Pavan

2
@BrianPan phương thức tĩnh và lớp không giống nhau. Chúng tương tự nhau nhưng lý do chúng được đặt tên khác nhau là chúng hoạt động khác nhau. Ví dụ, các phương thức tĩnh không thể được ghi đè.
Sulthan

190

Tất cả các chi tiết kỹ thuật đã được bao phủ độc đáo trong các câu trả lời khác. Tôi chỉ muốn chia sẻ một sự tương tự đơn giản mà tôi nghĩ là minh họa độc đáo sự khác biệt giữa một lớp và một thể hiện:

nhập mô tả hình ảnh ở đây

Một lớp giống như bản thiết kế của một ngôi nhà: Bạn chỉ có một bản thiết kế và (thông thường) bạn không thể làm điều đó nhiều với bản thiết kế.

nhập mô tả hình ảnh ở đây

Một ví dụ (hoặc một đối tượng ) là ngôi nhà thực tế mà bạn xây dựng dựa trên bản thiết kế: Bạn có thể xây dựng nhiều ngôi nhà từ cùng một bản thiết kế. Sau đó, bạn có thể sơn các bức tường một màu khác nhau trong mỗi ngôi nhà, giống như bạn có thể thay đổi độc lập các thuộc tính của từng thể hiện của một lớp mà không ảnh hưởng đến các thể hiện khác.


6
@JohannesFahrenkrug Giải thích rõ ràng khái niệm về lớp và đối tượng ở đây. Đây không phải là câu hỏi thực sự dành cho difference between class method and an instance method ;
Shekhu

1
Giải thích hoàn hảo về Class vs Instance của một lớp. Các lớp học là một khái niệm xa lạ với người mới và điều này giải thích nó theo cách cơ bản nhất của nó.
Alex McPherson

1
@JohannesFahrenkrug thực sự là một lời giải thích tốt, khiến tôi phải suy nghĩ làm thế nào cả hai khác nhau và khi nào sử dụng cả hai
ChenSmile 16/2/2016

1
Thật là một lời giải thích tuyệt vời :)
Praveenkumar

1
Tương tự tốt. Xin ai đó cung cấp cho anh chàng này một năm cung cấp pizza.
GeneCode

102

Giống như các câu trả lời khác đã nói, các phương thức cá thể hoạt động trên một đối tượng và có quyền truy cập vào các biến thể hiện của nó, trong khi một phương thức lớp hoạt động trên toàn bộ một lớp và không có quyền truy cập vào các biến của một thể hiện cụ thể (trừ khi bạn chuyển thể hiện trong như một tham số).

Một ví dụ điển hình của phương thức lớp là phương thức kiểu đối lập, trả về tổng số thể hiện của một lớp. Các phương thức lớp bắt đầu bằng một +, trong khi các thể hiện bắt đầu bằng một -. Ví dụ:

static int numberOfPeople = 0;

@interface MNPerson : NSObject {
     int age;  //instance variable
}

+ (int)population; //class method. Returns how many people have been made.
- (id)init; //instance. Constructs object, increments numberOfPeople by one.
- (int)age; //instance. returns the person age
@end

@implementation MNPerson
- (id)init{
    if (self = [super init]){
          numberOfPeople++;
          age = 0;
    }    
    return self;
}

+ (int)population{ 
     return numberOfPeople;
}

- (int)age{
     return age;
}

@end

chính

MNPerson *micmoo = [[MNPerson alloc] init];
MNPerson *jon = [[MNPerson alloc] init];
NSLog(@"Age: %d",[micmoo age]);
NSLog(@"%Number Of people: %d",[MNPerson population]);

Đầu ra: Tuổi: 0 Số người: 2

Một ví dụ khác là nếu bạn có một phương thức mà bạn muốn người dùng có thể gọi, đôi khi thật tốt khi biến nó thành một phương thức lớp. Ví dụ: nếu bạn có một lớp gọi là MathFifts, bạn có thể làm điều này:

+ (int)square:(int)num{ 
      return num * num;
}

Vì vậy, sau đó người dùng sẽ gọi:

[MathFunctions square:34];

mà không bao giờ phải khởi tạo lớp học!

Bạn cũng có thể sử dụng các hàm lớp để trả về các đối tượng được tự động phát hành, như của NSArray

+ (NSArray *)arrayWithObject:(id)object

Điều đó lấy một đối tượng, đặt nó vào một mảng và trả về một phiên bản tự động của mảng mà không phải quản lý bộ nhớ, tuyệt vời cho các mảng ôn đới và những gì không.

Tôi hy vọng bây giờ bạn hiểu khi nào và / hoặc tại sao bạn nên sử dụng các phương thức lớp !!


1
micmoo, tôi có thể đề nghị bạn đặt "static int numberOfP People = 0;" trong mã định dạng văn bản? Tôi đã bối rối cho đến khi tôi nhận thấy nó ở trên mã mẫu. Ngoài ra, một câu trả lời thực sự súc tích.
mobibob

2
Xin tha thứ cho người mới của tôi, nhưng tại sao bạn cần cả hai biến "tuổi" và phương thức "tuổi"? Không được getter và setter cho ví dụ "age" được tạo bằng @synthetize?
selytch

@selytch "tuổi" sẽ phải được xác định là một tài sản để sử dụng tổng hợp.
micah94

36

Một phương thức cá thể áp dụng cho một thể hiện của lớp (tức là một đối tượng) trong khi một phương thức lớp áp dụng cho chính lớp đó.

Trong C #, một phương thức lớp được đánh dấu tĩnh. Các phương thức và thuộc tính không được đánh dấu tĩnh là các phương thức thể hiện.

class Foo {
  public static void ClassMethod() { ... }
  public void InstanceMethod() { ... }
}

1
Argh - xin lỗi, tôi chỉ nhận thấy đây là một câu hỏi Obj-C. Hy vọng câu trả lời của tôi vẫn được áp dụng nhưng vui lòng bỏ phiếu xuống hoặc bỏ phiếu để xóa.
Robert Horvick

6
Không có tác hại. Phần đầu tiên trong câu trả lời của bạn là chính xác theo nguyên tắc OOP chung và nó chắc chắn áp dụng cho Objective-C. Bạn có thể thêm "object-c" vào danh sách các thẻ để bỏ qua nếu bạn không muốn xem những câu hỏi như vậy, mặc dù mọi sự tham gia chắc chắn đều được chào đón. :-)
Quinn Taylor

16

Câu trả lời cho câu hỏi của bạn không dành riêng cho object-c, tuy nhiên trong các ngôn ngữ khác nhau, các phương thức Class có thể được gọi là phương thức tĩnh.

Sự khác biệt giữa các phương thức lớp và phương thức cá thể là

Phương thức lớp

  • Hoạt động trên các biến Class (chúng không thể truy cập các biến thể hiện)
  • Không yêu cầu một đối tượng được khởi tạo để được áp dụng
  • Đôi khi có thể là mùi mã (một số người mới sử dụng OOP sử dụng như một cái nạng để thực hiện Lập trình có cấu trúc trong môi trường OO)

Phương pháp sơ thẩm

  • Hoạt động trên các biến thể hiện và biến lớp
  • Phải có một đối tượng cố định để hoạt động trên

Phương pháp sơ thẩm có thể hoạt động trên các biến lớp?
蘇健豪

16

Tôi nghĩ rằng cách tốt nhất để hiểu điều này là nhìn vào allocinit. Chính lời giải thích này đã cho phép tôi hiểu được sự khác biệt.

Phương pháp lớp học

Một phương thức lớp được áp dụng cho toàn bộ lớp. Nếu bạn kiểm tra allocphương thức, đó là một phương thức lớp được biểu thị bằng +trước khi khai báo phương thức. Đây là một phương thức lớp vì nó được áp dụng cho lớp để tạo một thể hiện cụ thể của lớp đó.

Phương pháp sơ thẩm

Bạn sử dụng một phương thức cá thể để sửa đổi một thể hiện cụ thể của một lớp duy nhất cho cá thể đó, thay vì toàn bộ lớp. initví dụ (được biểu thị bằng a -trước khi khai báo phương thức), là một phương thức thể hiện bởi vì bạn thường sửa đổi các thuộc tính của lớp đó sau khi nó được tạo bằng alloc.

Thí dụ

NSString *myString = [NSString alloc];

Bạn đang gọi phương thức lớp allocđể tạo một thể hiện của lớp đó. Lưu ý cách người nhận tin nhắn là một lớp.

[myString initWithFormat:@"Hope this answer helps someone"];

Bạn đang sửa đổi thể hiện của cuộc NSStringgọi myStringbằng cách đặt một số thuộc tính trên thể hiện đó. Lưu ý cách người nhận tin nhắn là một thể hiện (đối tượng của lớp NSString).


Bạn có ý nghĩa gì khi kiểm tra phương pháp "phân bổ"? Bạn có thể chỉ cho tôi một nơi cụ thể trong tài liệu? (chỉnh sửa) -> ahh nevermind, yeah trong tài liệu NSObject nó nói rằng dưới "Nhiệm vụ" - developer.apple.com/library/ios/documentation/cocoa/reference/...
Ethan Parker

Bạn không thực sự cần phải hiểu những gì nó thực sự nắm bắt được điều này, chỉ là nó được áp dụng cho lớp học. Nói một cách đơn giản: allocphân bổ đủ bộ nhớ cho đối tượng, initsẽ sửa đổi những gì trong các địa chỉ bộ nhớ đó để xác định trạng thái của đối tượng. Chúng tôi không thể sửa đổi một đối tượng trừ khi có không gian để sửa đổi nó, vì vậy chúng tôi sử dụng alloctrên lớp sẽ quyết định cung cấp cho chúng tôi không gian đó.
Adam Chờ đợi

6

Các phương thức lớp thường được sử dụng để tạo các thể hiện của lớp đó

Ví dụ, [NSString stringWithFormat:@"SomeParameter"];trả về một NSStringthể hiện với tham số được gửi đến nó. Do đó, vì nó là một phương thức Class trả về một đối tượng cùng loại, nên nó còn được gọi là phương thức tiện lợi.


6

Vì vậy, nếu tôi hiểu chính xác.

Một classphương thức không cần bạn phân bổ thể hiện của đối tượng đó để sử dụng / xử lý nó. Một classphương thức được khép kín và có thể hoạt động mà không phụ thuộc vào trạng thái của bất kỳ đối tượng nào của lớp đó. Một classphương thức được dự kiến ​​sẽ phân bổ bộ nhớ cho tất cả công việc của chính nó và phân bổ khi hoàn thành, vì không có trường hợp nào của lớp đó có thể giải phóng bất kỳ bộ nhớ nào được phân bổ trong các cuộc gọi trước đó cho phương thức lớp.

Một instancephương pháp thì ngược lại. Bạn không thể gọi nó trừ khi bạn phân bổ một thể hiện của lớp đó. Nó giống như một lớp bình thường có hàm tạo và có thể có hàm hủy (giúp dọn sạch tất cả bộ nhớ được phân bổ).

Trong hầu hết các khả năng (trừ khi bạn đang viết một thư viện có thể sử dụng lại, bạn không cần một classbiến.


1
Một trường hợp rõ ràng khi bạn cần các phương thức lớp là việc tạo các thể hiện. Bạn phải có thể tạo phiên bản mà không có bất kỳ trường hợp nào, nếu không phiên bản đầu tiên không bao giờ có thể được tạo. Đó là lý do tại sao + alloc là và phải là một phương thức lớp.
gnasher729

4

Các phương thức thể hiện hoạt động trên các thể hiện của các lớp (tức là "các đối tượng"). Các phương thức lớp được liên kết với các lớp (hầu hết các ngôn ngữ sử dụng từ khóa staticcho những người này).


3

Lấy ví dụ một trò chơi trong đó rất nhiều xe được sinh ra .. mỗi chiếc thuộc về lớp CCar. Khi một chiếc xe được khởi tạo, nó sẽ gọi

[CCar registerCar:self]

Vì vậy, lớp CCar, có thể lập danh sách mọi CCar ngay lập tức. Giả sử người dùng hoàn thành một cấp độ và muốn xóa tất cả ô tô ... bạn có thể: 1- Đi qua danh sách mọi CCar bạn đã tạo thủ công và thực hiện whicheverCar.remove(); hoặc 2- Thêm phương thức removeAllCars vào CCar, điều này sẽ làm điều đó cho bạn khi bạn gọi [CCar remove ALLCars]. I E allCars[n].remove();

Hoặc ví dụ: bạn cho phép người dùng chỉ định kích thước phông chữ mặc định cho toàn bộ ứng dụng, được tải và lưu khi khởi động. Nếu không có phương thức lớp, bạn có thể phải làm một cái gì đó như

fontSize = thisMenu.getParent().fontHandler.getDefaultFontSize();

Với phương thức lớp, bạn có thể thoát khỏi [FontHandler getDefaultFontSize].

Đối với chức năng removeVowels của bạn, bạn sẽ thấy rằng các ngôn ngữ như C # thực sự có cả hai phương thức nhất định như toLower hoặc toUpper.

ví dụ myString.removeVowels()String.removeVowels(myString) (trong ObjC sẽ là [String removeVowels:myString]).

Trong trường hợp này, cá thể có khả năng gọi phương thức lớp, vì vậy cả hai đều có sẵn. I E

public function toLower():String{
  return String.toLower();
}

public static function toLower( String inString):String{
 //do stuff to string..
 return newString;
}

về cơ bản, myString.toLower() các cuộc gọi [String toLower:ownValue]

Không có câu trả lời dứt khoát, nhưng nếu bạn cảm thấy muốn đưa một phương thức lớp vào sẽ cải thiện mã của bạn, hãy thử và lưu ý rằng một phương thức lớp sẽ chỉ cho phép bạn sử dụng các phương thức / biến lớp khác.


3

phương pháp lớp

là các phương thức được khai báo là tĩnh. Phương thức có thể được gọi mà không tạo một thể hiện của lớp. Các phương thức lớp chỉ có thể hoạt động trên các thành viên lớp chứ không phải các thành viên thể hiện vì các phương thức lớp không biết về các thành viên thể hiện. Các phương thức sơ thẩm của lớp cũng không thể được gọi từ bên trong một phương thức lớp trừ khi chúng được gọi trong một thể hiện của lớp đó.

Phương pháp sơ thẩm

mặt khác yêu cầu một thể hiện của lớp tồn tại trước khi chúng có thể được gọi, do đó, một thể hiện của một lớp cần được tạo bằng cách sử dụng từ khóa mới. Phương thức sơ thẩm hoạt động trên các trường hợp cụ thể của các lớp. Các phương thức sơ thẩm không được khai báo là tĩnh.


Nó cũng có thể được tạo bằng từ khóa "phân bổ" không chỉ từ "mới". Ngoài ra, Objective-C không yêu cầu một cá thể tồn tại để gọi một phương thức cá thể, bạn có thể gửi tin nhắn đến một con trỏ null.
Elviss Strazdins 11/03/2015

3

Trong Objective-C, tất cả các phương thức đều bắt đầu bằng ký tự "-" hoặc "+". Thí dụ:

@interface MyClass : NSObject
// instance method
- (void) instanceMethod;

+ (void) classMethod;
@end

Các ký tự "+" và "-" xác định xem một phương thức là một class methodhoặc một instance methodtương ứng.

Sự khác biệt sẽ rõ ràng nếu chúng ta gọi các phương thức này. Ở đây các phương thức được khai báo trong MyClass.

instance method yêu cầu một thể hiện của lớp:

MyClass* myClass = [[MyClass alloc] init];
[myClass instanceMethod];

Bên trong MyClasscác phương thức khác có thể gọi các phương thức MyClasssử dụng self:

-(void) someMethod
{
    [self instanceMethod];
}

Nhưng, class methodsphải được gọi trên chính lớp:

[MyClass classMethod];

Hoặc là:

MyClass* myClass = [[MyClass alloc] init];
[myClass class] classMethod];

Điều này sẽ không hoạt động:

// Error
[myClass classMethod];
// Error
[self classMethod];

3

PHƯƠNG PHÁP LỚP


Một phương thức lớp thường tạo ra một thể hiện mới của lớp hoặc lấy một số thuộc tính toàn cục của lớp. Các phương thức lớp không hoạt động trên một cá thể hoặc có bất kỳ quyền truy cập nào vào biến thể hiện.


PHƯƠNG PHÁP NGAY LẬP TỨC


Một phương thức cá thể hoạt động trên một thể hiện cụ thể của lớp. Ví dụ, phương thức truy cập mà bạn đã triển khai là tất cả các phương thức thể hiện. Bạn sử dụng chúng để đặt hoặc lấy các biến đối tượng của một đối tượng cụ thể.


HÓA ĐƠN


Để gọi một phương thức cá thể, bạn gửi tin nhắn đến một thể hiện của lớp.

Để gọi một phương thức lớp, bạn gửi tin nhắn trực tiếp đến lớp.


Nguồn: IOS - Objective-C - Phương thức lớp và phương thức sơ thẩm


1

Các phương thức lớp không thể thay đổi hoặc biết giá trị của bất kỳ biến thể hiện nào. Đó phải là tiêu chí để biết liệu một phương thức cá thể có thể là một phương thức lớp hay không.


-1 từ tôi, bởi vì bạn có thể truyền thể hiện cho phương thức lớp và nó sẽ có thể thay đổi và biết các giá trị của biến đó.
Elviss Strazdins 11/03/2015

1

Cũng cần nhớ, ý tưởng tương tự áp dụng cho các biến. Bạn sẽ bắt gặp các thuật ngữ như tĩnh, thành viên, thể hiện, lớp, v.v. khi nói về các biến giống như bạn làm cho các phương thức / hàm.

Có vẻ như thuật ngữ phổ biến trong cộng đồng Obj-C là ivar biến, nhưng tôi chưa phải là một chàng trai Obj-C.


1

Một bản cập nhật cho các câu trả lời ở trên, tôi đồng ý các phương thức cá thể sử dụng một thể hiện của một lớp, trong khi một phương thức lớp có thể được sử dụng chỉ với tên lớp.

Không còn có bất kỳ sự khác biệt nào giữa phương thức cá thể & phương thức lớp sau khi đếm tham chiếu tự động xuất hiện trong Objective-C.

Ví dụ: [NS StringWithformat:..]một phương thức lớp & [[NSString alloc] initwihtformat:..]một phương thức cá thể, cả hai đều giống nhau sau ARC


1

Lưu ý: Đây chỉ là định dạng mã giả

Phương pháp lớp

Hầu như tất cả những gì nó cần làm là trong thời gian biên dịch . Nó không cần bất kỳ đầu vào của người dùng, cũng như tính toán của nó dựa trên một thể hiện. Mọi thứ về nó đều dựa trên lớp / kế hoạch chi tiết, đó là duy nhất, tức là bạn không có nhiều bản thiết kế cho một lớp. Bạn có thể có các biến thể khác nhau trong thời gian biên dịch? Không, do đó, lớp này là duy nhất và do đó, bất kể bạn gọi một phương thức lớp bao nhiêu lần thì con trỏ trỏ tới nó sẽ giống nhau.

PlanetOfLiving: return @"Earth" // No matter how many times you run this method...nothing changes.

Phương pháp sơ thẩm

Trong trường hợp ngược lại, phương thức xảy ra trong thời gian chạy, vì chỉ khi đó bạn mới tạo ra một thể hiện của một cái gì đó có thể thay đổi theo mỗi lần khởi tạo.

initWithName: @"John" lastName: @"Doe"Age:12 @"cool"
initWithName: @"Donald" lastName: @"Drumpf"Age:5 attitude:@"He started"
initWithName: @"President" lastName: @"Obama"Age:54 attitude: @"Awesome"
//As you can see the value can change for each instance.

Nếu bạn đến từ các ngôn ngữ khác, các phương thức tĩnh giống như các phương thức lớp.
Nếu bạn đến từ Swift, các phương thức kiểu giống như các phương thức lớp.


0

Thêm vào câu trả lời trên

Phương thức lớp sẽ hoạt động trên lớp, chúng tôi sẽ sử dụng phương thức này cho mục đích chung trong đó như + stringWithFormat, kích thước của lớp và quan trọng nhất là cho init vv

NSString *str = [NSString stringWithFormat:@"%.02f%%",someFloat]; 

Phương thức sơ thẩm sẽ hoạt động trên một thể hiện của một lớp không thuộc một lớp như chúng tôi đang có hai người và chúng tôi muốn biết số dư của từng cá nhân ở đây, chúng tôi cần sử dụng phương thức cá thể. Bởi vì nó sẽ không trả lời chung. ví dụ như xác định số lượng NSSArray, v.v.

[johnson getAccountBalance];
[ankit getAccountBalance];
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.