注册

移动开发之语言之美 – 类

现在最受开发者欢迎的两大平台 IOS, android现在主要还使用Objective-C 和 Java 来进行开发,不过苹果公司推出的编程语言 Swift,她吐故纳新,抛弃了Objective C繁琐的语法规则,引入了极为简洁,功能强大的语法。实际上除了平台本身的限制,包括如何调用平台提供的API,如何使用线程,如何启动定时器,如何设计UI界面等等之外,语言本身其实都是大同小异,所以为了方便开发者掌握不同平台的语言,对比学习Swift,Objective-C,Java等移动开发主流语言也是一种不错的选择。
在这个篇章中,我们首先从类定义开始,逐步探讨继承,接口,访问控制

如果你学过面向对象编程的语言,你就知道类是个什么概念,简而言之,我们把某种具有共同属性及功能单元的设计蓝图称之为类,它代表的设计定义,而对象就是根据类定义所产生的内存实体。
我现在用一个简单的需求实例来阐明不同的语言是如何实现这个需求的,以便读者可以了解不同的语言是对类如何定义和实现的。
需求:
实现一个类包含4个变量 
  1. mExampleData 是integer类型
  2. mExampleStr是字符串类型
  3. mExampleBool 布尔类型
  4. exampleProperty 是int类型
  5. 但是exampleProperty是可以通过api进行改变的

包含5个函数
构造函数
  1. exampleFunc函数没有任何返回值和参数
  2. exampleFuncWithParameters 没有返回值但是有一个字符串参数,和 布尔型参数
  3. exampleFuncWithReturnValue 返回值为字符,但没有参数的函数
  4. classExampleFunc 静态或者类函数

Objective-C 定义
@interface YN_Example_Class : NSObject{
@private
int mExampleData; 
 
@protected
NSString* mExampleStr;
 
@public
BOOL mExampleBool;
}
 
-(YN_Example_Class*) init;
 
@property(nonatomic) int exampleProperty;
 
-(void) exampleFunc;
-(void) exampleFuncWithParameters:(NSString*) str withBool:(BOOL) boolP;
-(NSString*) exampleFuncWithReturnValue;
 
+(void) classExampleFunc;
Objective-C 类实现
@implementation YN_Example_Class 
 
-(YN_Example_Class*) init{
mExampleStr = @"YN_Example_Class";
mExampleData = 8;
mExampleBool = YES;
return self;
}
 
-(void) exampleFunc{
NSLog(@"exampleFunc");
}
 
-(void) exampleFuncWithParameters:(NSString *)str withBool:(BOOL) boolP{
mExampleStr = str;
mExampleBool = boolP;
}
 
-(NSString*) exampleFuncWithReturnValue{
return mExampleStr;
}
 
+(void) classExampleFunc{
NSLog(@"classExampleFunc");
}
 
-(void) setExampleProperty: (int) data{
if(_exampleProperty < 100){
_exampleProperty = data;
}
}
 
-(int) getExampleProperty{
_exampleProperty++;
return _exampleProperty;
}
 
@end
Swift
class YN_Example_class{
var mExampleStr:String
var mExampleData:UInt
var mExampleBool:Bool 
 
var exampleProperty:UInt{
get{
mExampleData++
return mExampleData;
}
 
set(data){
if(mExampleData < 100){ mExampleData = data } } } init(){ mExampleStr = "YN_Example_class" mExampleData = 8 mExampleBool = true } func exampleFunc(){ println("exampleFunc") } func exampleFuncWithParameters(str:String, boolP:Bool){ mExampleStr = str; mExampleBool = boolP } func exampleFuncWithReturnValue() -> String{
return mExampleStr
}
 
class func exampleClassFunc(){
println("exampleClassFunc")
}
}
Java​
class YN_Example_Class{
private int mExampleData;
protected String mExampleStr;
public boolean mExampleBool;
private int exampleProperty;
static private String gStr;
 
YN_Example_Class(){
mExampleStr = "YN_Example_Class";
mExampleData = 8;
mExampleBool = true;
setExampleProperty(0);
}
 
void exampleFunc(){
System.out.println("exampleFunc");
}
 
void exampleFuncWithParameters(String str, boolean boolP){
mExampleStr = str;
mExampleBool = boolP;
}
 
String exampleFuncWithReturnValue(){
return mExampleStr;
}
 
static void classExampleFunc(){
System.out.println("classExampleFunc");
}
 
public int getExampleProperty() {
exampleProperty++;
return exampleProperty;
}
 
public void setExampleProperty(int exampleProperty) {
if(this.exampleProperty < 100){
this.exampleProperty = exampleProperty;
}
}
}
 
属性property/成员变量
Objective-C既提供变量也提供属性的概念,实际上属性就是一种语法规则,属性本身并不存在内存中,但编译器为之合成一个内存实体叫_PropertyName,我们可以简单的理解为是用来替代麻烦的setter和getter操作,编译器会自动合成相应的setter和getter函数,不过属性定义的不同会导致setter和getter实现的不同。
为了简洁,去除混淆,Swift已经不再区分成员变量和property,她应经统一了二者,直接用关键字var来定义。
Swift 定义了两种propertyStored Property -- 可以理解为property直接存储数据
Computed Property -- 可以理解为property不能直接存储数据,而是通过getter,setter来间接存取exampleProperty就是个Computed Property
var example:YN_Example_class = YN_Example_class()
example.exampleProperty = 9;
println(example.exampleProperty)
example.exampleProperty 值为10
Java 和 Objective-c 还有 Swift不同之处就是,语言层面没有property的支持,不过无非就是多写两行代码,用来setter和getter成员变量
类函数/静态函数
直接了当的说,就是直接可以通过类名访问
YN_Example_Class.classExampleFunc
类变量/静态变量
用来做所有实例共享的变量,单例模式
swift,和Objective-C不能声明类变量在类里,Java一定要声明在类里。
Objective-C
#import
#import "objc_language_class.h"
static NSString* gStr; 
 
@implementation YN_Example_Delegate
Swift
import Foundation 
 
private var gStr:String?
类属性,所有的实例都共享同一个类属性,类属性一定是个Computed Property(看上述property属性),类属性的实现需要全局属性的支持,上述就是如何定义一个全局属性来存储数据
类属性例子如下:
class var gProperty:String {
set(g){
gStr = g
}
get{
return gStr!
}
}
Java
class YN_Example_Class{
static private String gStr;
接口,继承,重载
Swift
import Foundation 
 
protocol YNExample_Protocol{
func getMe() -> String
}
 
class YN_Example_Delegte : YNExample_Protocol{
var myproto:UInt
var myStr:String
init(){
myproto = 3;
myStr = String()
}
 
func getMe() -> String{
return "YN_Example_Delegte"
}
}
 
class YN_Example_Delegte_derived : YN_Example_Delegte{
// without override, complier will give the error
override func getMe() -> String{
return "YN_Example_Delegte_derived"
}
}
Objective-C
#ifndef objc_language_class_objc_language_class_h
#define objc_language_class_objc_language_class_h 
 
@protocol YN_Example_Protocol
 
-(NSString*) getMe;
@end
 
@interface YN_Example_Delegate : NSObject{
NSString* myStr;
}
 
@property int myprop;
 
-(YN_Example_Delegate*) init;
 
@end
 
@interface YN_Example_DelegateDerived : YN_Example_Delegate;
 
@end
 
#endif
 
static NSString* gStr;
 
@implementation YN_Example_Delegate
 
- (NSString*) getMe{
return @"YN_Example_Delegate";
}
 
-(YN_Example_Delegate*) init{
myStr = [[NSString alloc] initWithUTF8String:""];
return self;
}
 
@end
 
@implementation YN_Example_DelegateDerived
- (NSString*) getMe{
myStr = @"";
return @"YN_Example_DelegateDerived";
}
@end
Java
interface YNExample_Protocol{
String getMe();
}
 
class YN_Example_Delegte implements YNExample_Protocol{
 
@Override
public String getMe() {
// TODO Auto-generated method stub
return "YN_Example_Delegte";
}
}
 
class YN_Example_Delegte_derived extends YN_Example_Delegte{
@Override
public String getMe() {
// TODO Auto-generated method stub
return "YN_Example_Delegte_derived";
}
}
三种语言都不支持多继承,但是都支持多接口实现。
关于重载只有Swift硬性要求在重载的函数前加override,否者complier会报错
构造函数
Swift和Objective-C的默认构造函数都是init(),并且可以定制的构造函,只不过名称都必须命名为init只是参数不同,Java和C++一样都是类名开始的函数,但init有返回值,Java构造函数没有。可以参考上面代码。
Java 和 Objective-C默认都会调用父类的构造函数,但swift则不同,默认不调用除非以下情况:子类没有实现任何init构造函数
子类重载或新实现某些构造函数,但子类所有的property都必须要有默认的初始值,也就是在声明时赋的值
Swift 可以重载构造函数,不过必须要加override前缀
类探测API
Java:
用 instanceof 来探测类type
if(example instanceof YN_Example_Class){
System.out.println("is YN_Example_Class");
}
Swift:
用as来探测类type
delegate as YN_Example_Delegte
Objective-C
用isKindOfClass来探测类type
BOOL isClass = [delegate isKindOfClass:[YN_Example_DelegateDerived class]];
访问控制
Objective-C
其访问控制基本和C++一致

@private:      只有这个类可以访问
@protected:  此类和子类可访问
@public:       任何类都可以访问
默认权限是protected
Swift:
private:        只有在本源文件里的代码可以访问
internal:       只有在本module(例如,app,或framework)里可以访问
public:         没有限制,可以作为对外暴漏的接口,例如创建个library
默认权限是internal
Java:
private:       只有这个类可以访问,不可跨包访问
default:       只有本包得类可以访问,默认的类都是default
protected:本类和此类的子类可以访问,跨包可访问
public:        没有限制,所有类可以访问,跨包可以访问
默认权限是default
此文主要讲解不同的语言对类不同的定义和实现,哪些地方不同并且应该注意什么,不过从结构来看,大体语言都很类似。此文并没有讲解的面面俱到,例如教大家如何熟悉语言的基本语法,如何声明变量,如何写控制流,这些都需要读者自己写程序加以熟悉。
由于时间有限,如果有纰漏之处,还望提醒,我会及时改正,谢谢。
PS:如果需要源码,请发信给mailto : syyorient@outlook.com
作者: 隋云怡
[Reference]
https://itunes.apple.com/cn/book/swift-programming-language/id881256329?mt=11
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/I
 
 

0 个评论

要回复文章请先登录注册