Swift - Kế thừa

Khả năng có nhiều hơn dạng được định nghĩa là Thừa kế. Nói chung một lớp có thể kế thừa các phương thức, thuộc tính và chức năng từ một lớp khác. Các lớp có thể được phân loại thêm thành lớp con và lớp siêu.

  • Sub Class - khi một lớp kế thừa các thuộc tính, phương thức và hàm từ một lớp khác thì nó được gọi là lớp con

  • Super Class - Lớp chứa các thuộc tính, phương thức và hàm để kế thừa các lớp khác từ chính nó được gọi là siêu lớp

Các lớp Swift 4 chứa lớp cha gọi và truy cập các phương thức, thuộc tính, hàm và phương thức ghi đè. Ngoài ra, các trình quan sát thuộc tính cũng được sử dụng để thêm thuộc tính và sửa đổi các phương thức thuộc tính được lưu trữ hoặc tính toán.

Lớp cơ sở

Một Lớp không kế thừa các phương thức, thuộc tính hoặc chức năng từ một lớp khác được gọi là 'Lớp Cơ sở'.

class StudDetails {
   var stname: String!
   var mark1: Int!
   var mark2: Int!
   var mark3: Int!
   
   init(stname: String, mark1: Int, mark2: Int, mark3: Int) {
      self.stname = stname
      self.mark1 = mark1
      self.mark2 = mark2
      self.mark3 = mark3
   }
}

let stname = "Swift 4"
let mark1 = 98
let mark2 = 89
let mark3 = 76

print(stname)
print(mark1)
print(mark2)
print(mark3)

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

Swift 4
98
89
76

Lớp có tên lớp là StudDetails được định nghĩa là lớp cơ sở ở đây được sử dụng để chứa tên sinh viên và ba môn học đánh dấu là mark1, mark2 và mark3. Từ khóa 'let' được sử dụng để khởi tạo giá trị cho lớp cơ sở và giá trị lớp cơ sở được hiển thị trong sân chơi với sự trợ giúp của hàm 'print'.

Lớp con

Hành động dựa trên một lớp mới trên một lớp hiện có được định nghĩa là 'Lớp con'. Lớp con kế thừa các thuộc tính, phương thức và chức năng của lớp cơ sở của nó. Để định nghĩa một lớp con ':' được sử dụng trước tên lớp cơ sở

class StudDetails {
   var mark1: Int;
   var mark2: Int;
   
   init(stm1:Int, results stm2:Int) {
      mark1 = stm1;
      mark2 = stm2;
   }
   func print() {
      print("Mark1:\(mark1), Mark2:\(mark2)")
   }
}

class display : StudDetails {
   init() {
      super.init(stm1: 93, results: 89)
   }
}

let marksobtained = display()
marksobtained.print()

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

Mark1:93, Mark2:89

Lớp 'StudDetails' được định nghĩa là siêu lớp nơi khai báo điểm của sinh viên và lớp con 'display' được sử dụng để kế thừa các dấu từ siêu lớp của nó. Lớp con xác định dấu của sinh viên và gọi phương thức print () để hiển thị dấu sinh viên.

Ghi đè

Việc truy cập cá thể siêu lớp, các phương thức kiểu, cá thể, thuộc tính kiểu và lớp con subscripts cung cấp khái niệm ghi đè. Từ khóa 'override' được sử dụng để ghi đè các phương thức được khai báo trong lớp cha.

Quyền truy cập vào các Phương thức, Thuộc tính và Đăng ký Siêu lớp

Từ khóa 'super' được sử dụng như một tiền tố để truy cập các phương thức, thuộc tính và chỉ số con được khai báo trong lớp siêu

Ghi đè Quyền truy cập vào các phương thức, thuộc tính và chỉ số con
Phương pháp super.somemethod ()
Tính chất super.someProperty ()
Đăng ký siêu [someIndex]

Ghi đè phương thức

Các phương thức kiểu và trường hợp kế thừa có thể bị từ khóa 'override' ghi đè lên các phương thức được định nghĩa trong lớp con của chúng tôi. Ở đây print () được ghi đè trong lớp con để truy cập thuộc tính kiểu được đề cập trong siêu lớp print (). Ngoài ra, phiên bản mới của siêu lớp cricket () cũng được tạo ra dưới dạng 'cricinstance'.

class cricket {
   func print() {
      print("Welcome to Swift 4 Super Class")
   }
}

class tennis: cricket {
   override func print() {
      print("Welcome to Swift 4 Sub Class")
   }
}

let cricinstance = cricket()
cricinstance.print()

let tennisinstance = tennis()
tennisinstance.print()

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

Welcome to Swift Super Class
Welcome to Swift Sub Class

Ghi đè tài sản

Bạn có thể ghi đè thuộc tính lớp hoặc phiên bản được kế thừa để cung cấp bộ nhận và bộ định tuyến tùy chỉnh của riêng bạn cho thuộc tính đó hoặc thêm người quan sát thuộc tính để cho phép thuộc tính ghi đè quan sát khi giá trị thuộc tính cơ bản thay đổi.

Ghi đè người nhận và người định đoạt tài sản

Swift 4 cho phép người dùng cung cấp getter và setter tùy chỉnh để ghi đè thuộc tính kế thừa cho dù đó là thuộc tính được lưu trữ hay được tính toán. Lớp con không biết tên và kiểu thuộc tính được kế thừa. Do đó, điều cần thiết là người dùng cần chỉ định trong lớp con, tên và kiểu của thuộc tính ghi đè được chỉ định trong lớp siêu.

Điều này có thể được thực hiện theo hai cách -

  • Khi setter được xác định cho thuộc tính ghi đè, người dùng cũng phải xác định getter.

  • Khi chúng ta không muốn sửa đổi getter thuộc tính được kế thừa, chúng ta có thể chỉ cần chuyển giá trị được kế thừa bằng cú pháp 'super.someProperty' cho lớp siêu.

class Circle {
   var radius = 12.5
   var area: String {
      return "of rectangle for \(radius) "
   }
}

class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

Radius of rectangle for 25.0  is now overridden as 3

Ghi đè người quan sát tài sản

Khi một thuộc tính mới cần được thêm vào cho một thuộc tính kế thừa, khái niệm 'ghi đè thuộc tính' được giới thiệu trong Swift 4. Điều này thông báo cho người dùng khi giá trị thuộc tính được thừa kế bị thay đổi. Nhưng việc ghi đè không áp dụng cho các thuộc tính được lưu trữ không đổi được kế thừa và các thuộc tính được tính chỉ đọc được kế thừa.

class Circle {
   var radius = 12.5
   var area: String {
     return "of rectangle for \(radius) "
   }
}

class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

class Square: Rectangle {
   override var radius: Double {
      didSet {
         print = Int(radius/5.0)+1
      }
   }
}

let sq = Square()
sq.radius = 100.0
print("Radius \(sq.area)")

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

Radius of rectangle for 25.0  is now overridden as 3
Radius of rectangle for 100.0  is now overridden as 21

Thuộc tính cuối cùng để ngăn Ghi đè

Khi người dùng không cần người khác truy cập vào các phương thức, thuộc tính hoặc chỉ số con của lớp siêu cấp, Swift 4 giới thiệu thuộc tính 'cuối cùng' để ngăn ghi đè. Khi thuộc tính 'cuối cùng' được khai báo, các chỉ số con sẽ không cho phép ghi đè các phương thức, thuộc tính siêu lớp và các chỉ số con của nó. Không có quy định nào để có tài sản 'cuối cùng' trong 'siêu hạng'. Khi thuộc tính 'cuối cùng' được khai báo, người dùng bị hạn chế tạo thêm các lớp con.

final class Circle {
   final var radius = 12.5
   var area: String {
      return "of rectangle for \(radius) "
   }
}

class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

class Square: Rectangle {
   override var radius: Double {
      didSet {
         print = Int(radius/5.0)+1
      }
   }
}

let sq = Square()
sq.radius = 100.0
print("Radius \(sq.area)")

Khi chúng tôi chạy chương trình trên bằng sân chơi, chúng tôi nhận được kết quả sau:

<stdin>:14:18: error: var overrides a 'final' var
override var area: String {
^
<stdin>:7:9: note: overridden declaration is here
var area: String {
^
<stdin>:12:11: error: inheritance from a final class 'Circle'
class Rectangle: Circle {
^
<stdin>:25:14: error: var overrides a 'final' var
override var radius: Double {
^
<stdin>:6:14: note: overridden declaration is here
final var radius = 12.5

Vì siêu lớp được khai báo là 'cuối cùng' và các kiểu dữ liệu của nó cũng được khai báo là 'cuối cùng' nên chương trình sẽ không cho phép tạo thêm các lớp con và nó sẽ tạo ra lỗi.