- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
注:本小节总结协议以及依靠协议实现委托,这将在以后经常被使用。是一个非常重要的模块
看下官方的定义:协议定义了一个蓝图 , 规定了用来实现某一特定工作或者功能所必须的方法和属性,类、结构体、或者枚举类型都可以遵循协议, 并提供具体实现来完成协议定义的方法和功能 。 任意能够满足协议要求的类型都被成为遵循了这个协议
协议的关键字:protocol
协议的语法:
protocol Pro1{
//这里定义属性或者方法
}
要使一个类或者结构体遵循某个协议 , Class1: Pro1
只需要冒号加上协议名称就可以了 。 这时候这个类就必须实现协议中的属性和方法 。(可选的可以不实现,后面会说)
protocol Pro1{
var name:String{set get} //可读可写
var age:Int { get } //只读属性
static var status:Int {set get}
}
//遵循协议
struct Struct1 : Pro1 {
private var _name = ""
var name:String {
set{
_name = newValue
}
get{
return _name
}
}
var age = 18 //可以声明为可读可写的
static var status = 1 //类型方法。
}
class Class1: Pro1 {
var name = "class"
var age:Int{ return 19 } //也可以是只读
static var status = 0
}
这里可以看到遵循者实现协议的集中方式,包括可读可写的和只读的。注释非常清晰,就不再赘述。
在协议中你可以定义实例方法 , 也可以定义类方法 ,其方法和属性定义差不多。
protocol MethodPro{
func plus(a:Int , b:Int)->Int
static func toUpper(str:String)->String
}
class MethodClass: MethodPro {
func plus(a: Int, b: Int)->Int {
return a + b
}
class func toUpper(str: String)->String {
return str.uppercaseString
}
}
很简单的例子说明下 , 在协议中用static
在实现类里可以用static
或者 class
我们都知道,在结构体和枚举这种值类型的实例方法中 , 不能对自己的变量进行操作 , 如果一定要操作 ,就需要生命成变异方法 。 所在在协议中有时候也需要声明成变异方法让结构体或者媒体去实现 。(类实现的时候不需要加mutating)
protocol MulPro{
mutating func toggle();
}
enum Tog:MulPro{
case On , Off
mutating func toggle() {
switch self {
case On:
self = Off
case Off:
self = On
}
}
}
var t=Tog.Off
t.toggle()
print(t) //Tog.On
t.toggle()
print(t) //Tog.Off
注释很清楚就不用过多解释了
协议也可以要求自己的遵循者实现指定的构造器。
所以在协议中也可以这么写,
protocol A{
init(val:Int)
}
实现这个协议的必须有这样的构造器,可以是指定构造器或者便利构造器,都必须加上required
修饰符 ,这样 在所以继承这个类的子类也都必须实现这个构造器。(关于各种构造器的解释 看我以前的构造过程那个文章)
class B: A {
required init(val:Int){
}
}
注:如果类已经标记为final ,则不需要required修饰符 ,final类不能有子类
如果在协议中定义的是一个可失败构造器,那么在遵循者中必须实现可失败构造器 后者 非可失败
协议可以当做一个类型来时候 , 调用调用协议的方法调用的是其实现类的方法
有时候我们需要在协议中定义的方法 , 有得遵循者需要实现 , 有得不是必须去实现的。这时候就可以使用可选类型。
可选协议只能在含有 @objc
前缀的协议中生效,而且可选协议只能被类去实现 。
@objc protocol Op{
optional var name:String{set get} //可选类型
optional func play()
var age:Int{get}
}
这个协议定义了一个可选属性和一个可选方法还有一个age属性 , 在实现他得类中只有age是必须实现的 。其他两个都是可选的 。
protocol SayHelloDelegate{
func sayHello(name:String);
}
class ClassA {
var delegate:SayHelloDelegate?
var name = "lucy"
func play(){
delegate?.sayHello(name);
}
}
class ClassB:SayHelloDelegate {
var name="lily"
func sayHello(name:String) {
print("\(name) 请 \(self.name) 帮她 say Hello");
}
}
我们这里定义了一个协议 ,有个很简单的方法,sayHello
,在A中声明了这个协议变量 ,使用了其方法 ,但这个方法却交给B去实现 。这就是一个很简单的代理模式
var ca = ClassA();
var cb = ClassB()
ca.delegate = cb
//B代理A去实现方法
ca.play(); //lucy 请 lily 帮她 say Hello
这是一个很简单的例子 ,但这个模式一会肯定会有很复杂的用法
扩展用extension
关键字 ,后面应该会加上这个的讲解
protocol HTMLFormat{
func asHtml(str:String)->String
}
//可以对ClassB扩展实现协议
extension ClassB:HTMLFormat{
func asHtml(str: String)->String {
return "<html>\(str)</html>"
}
}
这里我们让我们前面看得ClassB
再次实现这个协议 。然后他就一共实现了两个协议 , 一个sayHello 一个 hmtl的
var cb1 = ClassB();
cb1.asHtml("dog") //<html>dog</html>
cb1.sayHello("aaa") //aaa 请 lily 帮她 say Hello
这时候这两个方法就都可以用了
当然我们的协议也是可以继承的 。这里就不再示例。
protocol C : class{
func say();
}
class D: C{
func say(){
print("hello word")
}
}
看一看知道怎么回事就行了,就是在结构体和枚举里面不能用得协议
protocol N{
var age:Int{set get}
}
class F:M,N {
var name = "zhangsan"
var age = 18
}
这里我们定义了两个协议 ,F 遵循了这两个协议 ,这时候 我们有个方法需要传入的参数类型是遵循了这两个协议的实例
func happy(mn:protocol<M,N>){
print("\(mn.name) 今年 \(mn.age) 岁了,非常开心!!")
}
var f=F()
happy(f) //zhangsan 今年 18 岁了,非常开心!!
这里F是满足这两个协议的
你可以使用 is``as?``as
来检测摸个实例是否遵循某个协议
print(f is M) //true
let c = f as M
print(c) //F
关于is
,as
等得用法 可以看上一节类型转换
extension M{
func sayGoodBye(){
print("good-bye")
}
}
在扩展协议中提供默认实现 ,如果在遵循者中实现了此协议,则使用遵循者中的实现
对此感到疯狂,真的缺少一些东西。 我有webpack 4.6.0,webpack-cli ^ 2.1.2,所以是最新的。 在文档(https://webpack.js.org/concepts/mod
object Host "os.google.com" { import "windows" address = "linux.google.com" groups = ["linux"] } obj
每当我安装我的应用程序时,我都可以将数据库从 Assets 文件夹复制到 /data/data/packagename/databases/ .到此为止,应用程序工作得很好。 但 10 或 15 秒后
我在 cc 模式缓冲区中使用 hideshow.el 来折叠我不查看的文件部分。 如果能够在 XML 文档中做到这一点就好了。我使用 emacs 22.2.1 和内置的 sgml-mode 进行 xm
已结束。此问题不符合 Stack Overflow guidelines .它目前不接受答案。 我们不允许提出有关书籍、工具、软件库等方面的建议的问题。您可以编辑问题,以便用事实和引用来回答它。 关闭
根据java: public Scanner useDelimiter(String pattern) Sets this scanner's delimiting pattern to a patt
我读过一些关于 PRG 模式以及它如何防止用户重新提交表单的文章。比如this post有一张不错的图: 我能理解为什么在收到 2xx 后用户刷新页面时不会发生表单提交。但我仍然想知道: (1) 如果
看看下面的图片,您可能会清楚地看到这一点。 那么如何在带有其他一些 View 的简单屏幕中实现没有任何弹出/对话框/模式的微调器日期选择器? 我在整个网络上进行了谷歌搜索,但没有找到与之相关的任何合适
我不知道该怎么做,我一直遇到问题。 以下是代码: rows = int(input()) for i in range(1,rows): for j in range(1,i+1):
我想为重写创建一个正则表达式。 将所有请求重写为 index.php(不需要匹配),它不是以/api 开头,或者不是以('.html',或'.js'或'.css'或'.png'结束) 我的例子还是这样
MVC模式代表 Model-View-Controller(模型-视图-控制器) 模式 MVC模式用于应用程序的分层开发 Model(模型) - 模型代表一个存取数据的对象或 JAVA PO
我想为组织模式创建一个 RDF 模式世界。您可能知道,组织模式文档基于层次结构大纲,其中标题是主要的分组实体。 * March auxiliary :PROPERTIES: :HLEVEL: 1 :E
我正在编写一个可以从文件中读取 JSON 数据的软件。该文件包含“person”——一个值为对象数组的对象。我打算使用 JSON 模式验证库来验证内容,而不是自己编写代码。符合代表以下数据的 JSON
假设我有 4 张 table 人 公司 团体 和 账单 现在bills/persons和bills/companys和bills/groups之间是多对多的关系。 我看到了 4 种可能的 sql 模式
假设您有这样的文档: doc1: id:1 text: ... references: Journal1, 2013, pag 123 references: Journal2, 2014,
我有这个架构。它检查评论,目前工作正常。 var schema = { id: '', type: 'object', additionalProperties: false, pro
这可能很简单,但有人可以解释为什么以下模式匹配不明智吗?它说其他规则,例如1, 0, _ 永远不会匹配。 let matchTest(n : int) = let ran = new Rand
我有以下选择序列作为 XML 模式的一部分。理想情况下,我想要一个序列: 来自 my:namespace 的元素必须严格解析。 来自任何其他命名空间的元素,不包括 ##targetNamespace和
我希望编写一个 json 模式来涵盖这个(简化的)示例 { "errorMessage": "", "nbRunningQueries": 0, "isError": Fals
首先,我是 f# 的新手,所以也许答案很明显,但我没有看到。所以我有一些带有 id 和值的元组。我知道我正在寻找的 id,我想从我传入的三个元组中选择正确的元组。我打算用两个 match 语句来做到这
我是一名优秀的程序员,十分优秀!