详解 Scala 面向对象相关知识

一、包

1. 作用

  • 区分相同名字的类
  • 当类很多时,可以很好的管理类
  • 控制访问范围

2. 声明语法

// 第一种:与 Java 一致,以 . 作为层级划分
package package_name// 第二种:以 {} 作为层级划分
/*1. 一个源文件中可以声明多个 package2. 子包中的类可以直接访问父包中的内容,而无需导包
*/
package package_level1 {package package_level2 {...}
}

3. 命名规则

  • 只能包含数字、字母、下划线,但不能用数字开头,也不要使用关键字
  • 一般按照 com.公司名.项目名.业务模块名 划分层级
package com {import com.tencent.Inner //父包访问子包需要导包object Outer {val out: String = "out"def main(args: Array[String]): Unit = {println(Inner.in)}}package tencent {object Inner {val in: String = "in"def main(args: Array[String]): Unit = {println(Outer.out) //子包访问父包无需导包}}}
}package com {package alibaba {}
}

4. 包对象

  • 概念:在 Scala 中可以为每个包定义一个与包同名的包对象,定义在包对象中的成员,可以作为其对应包下所有 class 和 object 的共享变量,可以被直接访问

  • 案例:

    /**Java 风格包,包名为 com.abc.demo包对象的源文件名:package.scalacom.abc.demo 下的 class 和 object 都能访问包对象的变量和方法
    */
    package object demo {val commonVal: String = "家里蹲"def commonFunc(): Unit = {println(s"他们正在${commonVal}")}
    }/**嵌套风格包,包层级为 com abc demo包对象可与包定义在同一文件中,但是要保证包对象与包声明在同一作用域中
    */
    package com {package abc {package demo {object TestDemo {def main(args: Array[String]): Unit = {println(school)}}}// 包对象与包声明要在同一作用域package object demo {val school: String = "AgriculturalUniversity"}}
    }// 包对象定义在与包不同的作用域,包对象变量访问不到
    /*
    package object demo {val school: String = "AgriculturalUniversity"
    }
    */

5. 导包

  • 默认导入的包:

    • import java.lang._
    • import scala._
    • import scala.Predef._
  • 导包语法:

    // 1. 在源文件文件首行导入包,与 Java 一致
    import com.abc.Fruit
    package com.abc.demo
    object Test {...
    }// 2. 局部导入:在使用时导入,仅在当前作用域可以使用
    package com.abc.demo
    object Test {def main(args: Array[String]): Unit = {import com.abc.Fruit...}def f1(): Unit = {// Fruit 类访问不到}
    }// 3. 通配符导入
    import java.util._// 4. 给类起名
    import java.util.{ArrayList=>JL}// 5. 导入相同包的多个类
    import java.util.{HashSet, ArrayList}// 6. 屏蔽类
    import java.util.{ArrayList =>_,_}// 7. 导入包的绝对路径
    new _root_.java.util.HashMap
  • 案例说明:

    案例说明
    import com.abc.Fruit引入 com.abc 包下 Fruit(class 和 object)
    import com.abc._引入 com.abc 下的所有成员
    import com.abc.Fruit._引入 Fruit(object) 的所有成员
    import com.abc.{Fruit,Vegetable}引入 com.abc 下的 Fruit 和 Vegetable
    import com.abc.{Fruit=>Shuiguo}引入 com.abc 包下的 Fruit 并更名为 Shuiguo
    import com.abc.{Fruit=>Shuiguo,_}引入 com.abc 包下的所有成员,并将 Fruit 更名为 Shuiguo
    import com.abc.{Fruit=>_,_}引入 com.abc 包下屏蔽 Fruit 类
    new _root_.java.util.HashMap引入的 Java 的绝对路径

二、类和对象

1. 概念

  • 类:对象的抽象或模板
  • 对象:表示具体的事物

2. 语法

object Test {def main(args: Array[String]): Unit = {val student = new Student()// student.name // 报错,私有属性不能访问println(student.age)println(student.gender)student.age = 18println(student.age)println(student.getStuId)student.setStuId("002")println(student.getStuId)}
}/*声明类语法:[修饰符] class class_name {属性方法}
*/
class Student { // 默认为 public,不能显示的用 public 修饰private val name: String = "李雷" // 属性默认为 publicvar age: Int = _ // _ 表示属性默认值,Int 为 0,String 为 null, Boolean 为 falsevar gender: String = _ // _ 只能给 var 型变量赋默认值@BeanPropertyvar stuId: String = "001" // @BeanProperty 可以自动生成规范的 setter/getter 方法
}// 一个 scala 源文件可以声明多个类
class teacher {...
}

三、封装

1. 概念

封装是把抽象出的数据和对数据的操作封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作(成员方法),才能对数据进行操作

2. 对比 Java

  • Java 封装:
    • 将属性进行私有化
    • 提供一个公共的 set 方法,用于对属性赋值
    • 提供一个公共的 get 方法,用于获取属性的值
  • Scala 封装:
    • Scala 中的 public 属性,底层实际为 private,并通过 get 方法(obj.field())和 set 方法(obj.field_=(value))对其进行操作,即底层已经实现封装操作
    • 通过 @BeanProperty 注解实现显式的 getter 和 setter 方法可以兼容 Java 框架

3. 访问权限

  • Scala 中属性和方法的默认访问权限为 public,但 Scala 中无 public 关键字
  • private 为私有权限,只在类的内部和伴生对象中可访问
  • protected 为受保护权限,Scala 中受保护权限比 Java 中更严格,同类、子类可以访问,同包无法访问(与 Java 不同)
  • private[包名] 增加包访问权限,包名下的其他类也可以访问
package com.abc.scala.test object Person {def main(args: Array[String]): Unit = {val person = new Person()person.say()println(person.name)println(person.age)}
}class Person {private var name: String = "bobo"protected var age: Int = 18var address: String = "幸福里"private[test] var sex: String = "男"def say(): Unit = {println(s"$name $age $address $sex")}
}class Worker extends Person {def test(): Unit = {// this.name // errorthis.age this.sex}override def say(): Unit = { // 重写父类方法println(s"$age $address $sex")}
}class Animal {def test: Unit = {// new Person().age // errornew Person().sex}
}package com.abc.scala.test2 
class Teacher extends Person {def test(): Unit = {// this.name // errorthis.age // this.sex // error}
}

4. 构造器

和 Java 一样,Scala 构造对象也需要调用构造方法,并且可以有任意多个构造方法

4.1 基本语法
/*Scala 类的构造器包括:主构造器和辅助构造器
*/
class class_name(param1: type1,...) {    //  主构造器def this(param1: type1,...) {   //  辅助构造器}def this(param1: type1,...) {   // 辅助构造器可以有多个...}
}
  • 辅助构造器,函数的名称为 this,可以有多个,编译器通过参数的个数及类型来区分
  • 辅助构造方法不能直接构建对象,必须直接或者间接调用主构造方法
  • 构造器调用其他另外的构造器,要求被调用构造器必须提前声明
4.2 案例
object Student {def main(args: Array[String]): Unit = {val student = new Studentstudent.Student()val student1 = new Student("张三")val student2 = new Student("李四", 20)}
}class Student() { // 无参构造器var name: String = _var age: Int = _println("1. 主构造器被调用")def this(name: String) {this()this.name = nameprintln("2. 辅助构造器一被调用")println(s"name:$name age:$age")}def this(name: String, age: Int) {this(name)this.age = ageprintln("3. 辅助构造器二被调用")println(s"name:$name age:$age")}def Student(): Unit = {println("普通方法被调用")}
}// 构造器私有化
class Teacher private() {...
}

5. 构造器参数

  • 说明:Scala 类的主构造器的形参包括三种类型

    • 未用任何修饰符修饰,此时参数是一个局部变量
    • var 修饰参数,作为类的成员属性使用,可以修改
    • val 修饰参数,作为类只读成员属性使用,不能修改
  • 案例:

    object TestConstructor {def main(args: Array[String]): Unit = {val student1 = new Student1("tom", 18)student1.printInfo()val student2 = new Student2("jack", 20)println(s"name:$student2.name age:$student2.age")studen2.name = "curry"println(s"name:$student2.name age:$student2.age")val student3 = new Student3("james", 25)// student3.name = "bob" // errorprintln(s"name:$student3.name age:$student3.age")var student4 = new Student4("james", 25)println(s"name:$student4.name age:$student4.age school:$student4.school")student4 = new Student4("james", 25, "ArtSchool")println(s"name:$student4.name age:$student4.age school:$student4.school")}
    }// 不使用修饰符
    class Student1(_name: String, _age: Int) {// 不推荐使用// var name: String = _name// var age: Int = _agedef printInfo(): Unit = {println(s"name:$name age:$age")}
    }// 使用 var 修饰符,推荐
    class Student2(var name: String, var age: Int) // 使用 val 修饰符
    class Student3(val name: String, val age: Int) // 使用 var 修饰符且有辅助构造器
    class Student4(var name: String, var age: Int) {var school: String = _def this(name: String, age: Int, school: String) {this(name, age)this.school = school}
    }
    

四、继承和多态

1. 继承

  • 语法:

    class SonClass extends ParentClass { // 1. scala 是单继承// 2. 子类继承父类的属性和方法
    }
  • 案例:

    object TestInherit {def main(args: Array[String]): Unit = {val stu1 = new Student("张三", 18) // 1-3val stu2 = new Student("李四", 20, "1001") // 1-3-4}
    }// 定义父类
    class Person() { // 空参主构造器var name: String = _var age: Int = _println("1. 父类的主构造器调用")def this(name: String, age: Int) {this()println("2. 父类的辅助构造器调用")this.name = namethis.age = age}def printInfo(): Unit = {println(s"Person: $name $age")}
    }// 定义子类
    class Student(name: String, age: Int) extends Person() { // 先调用父类主构造器var stdNo: String = _println("3. 子类的主构造器调用")def this(name: String, age: Int, stdNo: String) {this(name, age)println("4. 子类的辅助构造器调用")this.stdNo = stdNo}override def printInfo(): Unit = {println(s"Student: $name $age $stdNo")}
    }

2. 多态

2.1 动态绑定比较
  • Java

    public class TestDynamicBind {public static void main(String[] args) {Worker worker = new Worker();System.out.println(worker.name);worker.hello();worker.hi();System.out.println("================");Person person = new Worker();System.out.println(person.name); // person,静态绑定属性person.hello(); // hello worker,动态绑定方法// person.hi(); // error}
    }class Person {String name = "person";public void hello() {System.out.println("hello person");}
    }class Worker extends Person {String name = "worker";@overridepublic void hello() {System.out.println("hello worker");}public void hi() {System.out.println("hi worker");}
    }
  • Scala

    object TestDynamicBind {def main(args: Array[String]): Unit = {val person: Person = new Workerprintln(person.name) // worker,动态绑定属性person.hello()  // hello worker,动态绑定方法}
    }class Person {val name: String = "person"def hello(): Unit = {println("hello person")}
    }class Worker extends Person {override val name: String = "worker"override def hello(): Unit = {println("hello worker")}
    }
    
2.2 多态案例
object TestMultiStatus {def main(args: Array[String]): Unit = {def printInfo(person: Person): Unit = {person.printInfo()}val person = new Personval student = new Studentval teacher = new Teacher// 通过动态绑定技术实现同一父类的不同具体实现,调用不同的方法printInfo(person) // hello personprintInfo(student) // hello studentprintInfo(teacher) // hello teacher}
}class Person {def printInfo(): Unit = {println("hello person")}
}class Student extends Person {override def printInfo(): Unit = {println("hello student")}
}class Teacher extends Person {override def printInfo(): Unit = {println("hello teacher")}
}

五、抽象类

1. 定义

  • 抽象类:使用 abstract 关键字修饰,相当于模板类,可以包含抽象的属性方法和非抽象的属性方法,可以被继承
  • 抽象属性:没有初始值的属性,只能存在于抽象类中,可以被继承实现
  • 抽象方法:没有具体实现的方法,只能存在于抽象类中,可以被继承实现
object TestAbstractClass {def main(args: Array[String]): Unit = {val student: Student = new Studentprintln(student.name)println(student.age)println(student.stuNo)student.eat()student.sleep()}
}// 定义抽象类
abstract class Person {// 非抽象属性val name: String = "person"var age: Int = 19// 抽象属性var stuNo: String// 非抽象方法def eat(): Unit = {println("person eat")}// 抽象方法def sleep(): Unit
}// 定义继承类
class Student extends Person { // 继承类也可以定义为抽象类override val name: String = "student"// override var age: Int = 20 // error,var 属性不能被重写age = 20var stuNo: String = "1001" // 实现抽象属性override def eat(): Unit = { // 重写方法super.eat() // 调用父类的非抽象方法println("student eat")}def sleep(): Unit = { // 实现抽象方法,可以不加 overrideprintln("student sleep")}
} 

2. 匿名子类

object TestAnnoymousClass {def main(args: Array[String]): Unit = {val person: Person = new Person {var name: String = "张三"def eat(): Unit = println("张三 eat")}println(person.name)person.eat()}
}abstract class Person {var name: Stringdef eat(): Unit
}

六、单例对象

伴生对象

1. 定义

​ Scala 语言是完全面向对象的语言,所以并没有静态的概念和操作。为了能够和 Java 语言交互,就产生了一种特殊的对象来模拟类对象, 该对象为单例对象,也称为类的伴生对象。伴生对象名必须与类名一致,这个类的所有“静态”内容都可以在它的伴生对象中声明

2. 语法案例

// 定义一个类
class Student(val name: String, val age: Int) {def printInfo(): Unit = {println(s"student: name=$name age=$age school=$Student.school")}
}// 定义类的伴生对象
object Student { // 关键字 object,对象名与类名一致// 定义静态的属性val school: String = "highSchool"
}object TestObject {def main(args: Array[String]): Unit = {val student1 = new Student("tom", 18)val student2 = new Student("jerry", 19)// school 的值是一样的student1.printInfo()student2.printInfo()}
}

3. apply 方法

通过伴生对象的 apply 方法,可以实现不使用 new 方法创建对象

// 定义一个类
class Student private(val name: String, val age: Int) { // 构造方法私有化def printInfo(): Unit = {println(s"student: name=$name age=$age school=$Student.school")}
}// 定义类的伴生对象
object Student { // 关键字 object,对象名与类名一致// 定义静态的属性val school: String = "highSchool"// 定义 apply 方法,创建伴生类的对象实例def apply(name: String, age: Int): Student = new Student(name, age)// apply 方法可以重载def apply(): Student = {null}
}object TestObject {def main(args: Array[String]): Unit = {val student1 = Student.apply("tom", 18)val student2 = Student("tom", 18) // apply 方法名可以省略val student3 = Student()student1.printInfo()student2.printInfo()}
}

4. 单例设计模式实现

object TestSingleton {def main(args: Array[String]): Unit = {val obj1 = Singleton.getInstance()val obj2 = Singleton.getInstance()println(obj1)println(obj2)}
}class Singleton private(name: String, age: Int) {}object Singleton {// 饿汉式// private val obj: Singleton = new Singleton("孙悟空", 500)// def getInstance(): Singleton = obj// 懒汉式private var obj: Singleton = _def getInstance(): Singleton = if(obj == null) new Singleton("孙悟空", 500) else obj
}

七、特质

1. 定义

  • Scala 语言中,采用特质 (trait) 来代替接口的概念,当多个类具有相同的特质(特征)时,就可以将这个特质独立出来,采用关键字 trait 声明
  • Scala 中的 trait 中既可以有抽象属性和方法,也可以有具体的属性和方法,一个类可以混入(mixin)多个特质
  • Scala 引入 trait 特征,第一可以替代 Java 的接口,第二个也是对单继承机制的一种补充;同时所有的 Java 接口都可以当做 Scala 特质使用

2. 基本语法

/** 特质声明语法:trait traitName {}
*/
trait PersonTrait {// 定义抽象和非抽象属性val name: String = "tom"var age: Int// 定义抽象和非抽象方法def say(): Unit = {println("person can say")}def eat(): Unit}

3. 特质混入

  • 语法:

    /** 使用 extends 和 with 关键字为类混入特质
    */// 存在父类
    class SonClass extends ParentClass with trait1 with trait2 {}// 没有父类
    class SubClass extends trait1 with trait2 with trait3 {}
  • 案例:

    object TestMixIn {def main(args: Array[String]): Unit = {val student1 = new Studentstudent1.eat()student1.study()student1.increase()student1.play()student1.increase()student1.dating()student1.increase()println("===================")// 动态混入val studentWithTalent = new Student with Talent {override def singing(): Unit = println("student is good at singing")override def dancing(): Unit = println("student is good at dancing")}studentWithTalent.eat()studentWithTalent.study()studentWithTalent.increase()studentWithTalent.play()studentWithTalent.increase()studentWithTalent.dating()studentWithTalent.increase()studentWithTalent.singing()studentWithTalent.dancing()}
    }class Person {val name: String = "person"val age: Int = 1def eat(): Unit = println(s"person $name is eating")
    }trait Young {val name: String = "young"var age: Intdef play(): Unit = println("young person $name is playing")def dating(): Unit
    }trait Kownledge {var amount: Int = 0def increase(): Unit
    }trait Talent {def singing(): Unitdef dancing(): Unit
    }class Student extends Person with Young with Kownledge {// 存在多个同名的非抽象属性,必须重写override val name: String = "student"// 实现抽象方法def dating(): Unit = println(s"student $name is dating")def increase(): Unit = {amount += 1println(s"$name kownledge is increasing")}// 定义自有方法def study(): Unit = println(s"student $name is studying")// 重写父类方法override def eat(): Unit = println(s"student $name is eating")
    }
    

4. 特质叠加

4.1 问题引出

​ 由于一个类可以继承 (extends) 父类和混入 (mixin) 多个 trait,当继承的父类和混入的特质中具有相同的属性和相同的方法 (方法名/参数列表/返回值均相同) 时,必然会出现继承冲突问题

​ 继承冲突分为两种情况:第一种是混入的多个 trait 中具有相同的具体方法,且 trait 之间没有任何关系;混入的多个 trait 中具有相同的具体方法,且 trait 都继承自相同的父 trait,即钻石冲突问题

4.2 解决方法
  • 第一种冲突:

    object TestOverly {def main(args: Array[String]): Unit = {val student = new Studentprintln(student.name)student.hello() // talent hello - student hello}
    }class Person {val name: String = "person"def hello(): Unit = {println("person hello")}
    }trait Kownledge {val name: String = "kownledge"def hello(): Unit = {println("kownledge hello")}
    }trait Talent {val name: String = "talent"def hello(): Unit = {println("talent hello")}
    }class Student extends Person with Kownledge with Talent {// 冲突属性必须重写override val name: String = "student"// 冲突方法必须重写override def hello(): Unit = {super.hello() // 调用的是最后一个混入特质的该方法println("student hello")}
    }
  • 第二种冲突:

    object TestOverly {def main(args: Array[String]): Unit = {val myBall = new MyBallprintln(myBall.describe()) // my ball is a red-foot-ball}
    }trait Ball {def describe(): String = {"ball"}
    }trait ColorBall {val color: String = "red"def describe(): String = {color + "-" + super.describe()}
    }trait CategoryBall {val category: String = "foot"def describe(): String = {category + "-" + super.describe()}
    }class MyBall extends CategoryBall with ColorBall {// 冲突方法必须重写override def describe(): String = {// super调用采用特质叠加的策略// 先调用最后一个混入特质的方法再从右往左调用与其同父特质的特质的方法最后调用父特质的方法"my ball is a " + super.describe() // 如果想要调用某个指定的混入特质中的方法,可以增加约束:super[traitName]// "my ball is a " + super[CategoryBall].describe() }
    }
    

5. 特质自身类型

5.1 概念
  • 特质自身类型是在特质或类中定义一个外部的类或特质的持有,相当于 Java Spring 中的依赖注入

  • 语法:

    trait traitName {/*_ 表示自身类型别名的通配type 是持有的具体类名或特质名*/_: type =>
    }
    
5.2 案例

模拟用户注册

object TestSelfType {def main(args: Array[String]): Unit = {val regUser = new RegUser("bob", "123456")regUser.insertUser()}
}// 定义用户类
class User(var name: String, var password: String)// 定义用户操作特质
trait UserDao {// 使用特质自身类型将 User 类引入,类似于 spring 的依赖注入/*  @Autowiredprivate User user;*/_: User =>// 插入用户信息到数据库def insertUser(): Unit = { // 方法通过自身类型 this 可以获取 User 信息println(s"insert into user:${this.name} into db")}
}// 定义注册用户类,继承用户类并混入用户操作特质
class RegUser(name: String, password: String) extends User(name, password) with UserDao

6 特质VS抽象类

  • 优先使用特质,一个类扩展多个特质是很方便的,但却只能扩展一个抽象类
  • 如果需要构造函数参数,则使用抽象类。因为抽象类可以定义带参数的构造函数,而特质不行 (有无参构造器)

八、扩展

1. 类型检查和转换

class Personclass Student extends Personobject TestExtends {def main(args: Array[String]): Unit = {val person: Person = new Personval person2: Person = new Studentval student: Student = new Student//(1)判断对象是否为某个类型的实例:isInstanceOf[className]val res1: Boolean = person.isInstanceOf[Person] // trueval res2: Boolean = person.isInstanceOf[Student] // falseval res3: Boolean = person2.isInstanceOf[Student] // trueval res4: Boolean = student.isInstanceOf[Person] // true//(2)将对象转换为某个类型的实例:asInstanceOf[className]if (res3) { // 首先对象必须为该类型实例才能转换val student2: Student = person2.asInstanceOf[Student]println(student2)}//(3)获取类的信息:classOf[className]val pClass: Class[Person] = classOf[Person]println(pClass)}
}

2. 枚举类和应用类

/*枚举类定义语法:object objName extends Enumeration {val fieldName = Value(i: Int, value: String)}
*/
object WorkDay extends Enumeration {val MONDAY = Value(1, "星期一") // 枚举类属性一般全大写val TUESDAY = Value(2, "星期二")
}/*应用类定义语法:object objName extends App {// 可执行的语句}
*/
object MyApp extends App { // 必须定义为 object// 省略了 main 方法,内部有 main 方法的封装println(WorkDay.MONDAY)
} 

3. Type 定义新类型

// 使用 type 关键字可以定义新的数据数据类型名称,本质上就是类型的一个别名
object Test {def main(args: Array[String]): Unit = {type MyString = Stringvar str: MyString = "abc"def test(): MyString = "xyz"}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/843958.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CentOS 7如何使用systemctl管理应用

说明:本文介绍如何使用systemctl命令的方式来启动、查看、停止和重启应用,以安装后的prometheus、alertmanager为例; Step1:创建文件 在系统/etc/systemd/system/路径下,创建一个xxx.service文件,该文件内…

【LinuxC语言】glob函数

文章目录 前言glob函数介绍函数原型参数说明返回值`glob_t`结构示例代码globfree函数介绍参数说明总结前言 在Linux系统编程中,经常需要操作文件和目录,尤其是处理文件名模式匹配的情况,例如查找特定类型的文件或批量处理文件。C语言标准库提供了glob函数来满足这种需求,它…

【最优化方法】实验二 一维搜索方法的MATLAB实现

实验二  一维搜索方法的MATLAB实现 实验的目的和要求:通过本次实验应使学生掌握如何使用MATLAB软件进行一维搜索,并学会对具体问题进行分析。 实验内容: 1、0.618法的MATLAB实现 2、Fibonacci法的MATLAB实现 学…

机器学习(五) -- 监督学习(4) -- 集成学习方法-随机森林

系列文章目录及链接 上篇:机器学习(五) -- 监督学习(3) -- 决策树 下篇:机器学习(五) -- 监督学习(5) -- 线性回归1 前言 tips:标题前有“***”…

150.二叉树:二叉树的后序遍历(力扣)

代码解决 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr, right(nullptr) {}* Tree…

vite开发服务器server选项配置(2024-05-29)

server.host​ 类型: string | boolean默认: localhost 指定服务器应该监听哪个 IP 地址。 如果将此设置为 0.0.0.0 或者 true 将监听所有地址,包括局域网和公网地址。 也可以通过 CLI 使用 --host 0.0.0.0 或 --host 来设置。 NOTE 在某些…

Autoware 技术代码解读(三)

Tip: 如果你在进行深度学习、自动驾驶、模型推理、微调或AI绘画出图等任务,并且需要GPU资源,可以考虑使用Compshare的GPU算力云平台。他们提供高性价比的4090 GPU,按时收费每卡2.6元,月卡只需要1.7元每小时,并附带200G…

​一款开源的.NET程序集反编译、编辑和调试神器

前言 说到.NET相关的反编译工具大家脑海里第一个想到的工具是什么?ILSpy、dnSpy、还是dotPeek?咱们今天的主要内容是讲讲dnSpyEx(dnSpyEx是dnSpy项目的非官方Fork维护版本)这个开源的.NET程序集反编译、编辑和调试工具该如何使用…

TypeScript 学习笔记(十七):TypeScript 与现代前端构建工具的结合使用

TypeScript 学习笔记(十七):TypeScript 与现代前端构建工具的结合使用 1. 引言 在前几篇学习笔记中,我们探讨了 TypeScript 的基础知识、前后端框架的结合应用、测试与调试技巧、性能优化、前端架构设计、工具和生态系统,以及 TypeScript 与数据库的深度结合和第三方库的…

Redis教程(十八):Redis的Redisson的看门狗机制

传送门:Redis教程汇总篇,让你从入门到精通 Redisson的看门狗机制 Redisson的看门狗机制主要是指客户端在获取到锁之后,通过后台线程或定时任务自动续期的功能,以避免在锁持有期间因为处理时间过长而导致锁自动释放,进而确保操作的安全性与原子性。 这个机制的工作原理是…

对于异地项目,集团总部如何进行有效管理?

近几年,随着全球经济的发展和企业的崛起,越来越多的企业开始将业务扩展到不同的地理位置。这使得异地项目的管理成为了一个重要的挑战。异地项目指的是分布在不同地区或国家的项目,由总部或主要管理团队远程协调和管理。在这种情况下&#xf…

Burnout Drift Multiplayer(多人赛车游戏模板)

Burnout Drift Multiplayer是一个完整的项目,已在PC、Android、iOS和WebGL上发布的Burnout Drift系列中使用。 [包括最新版本的Realistic Car Controller Pro] PC、WebGL和Android演示 包括Burnout Drift系列的所有功能。您只需几分钟即可轻松添加自己的车辆、场景和配乐。 警…

Windows 下载安装Apache

一、官网下载 1、打开Apache官网http://httpd.apache.org,点击Download。 2、选择Windows版本,点击链接。 3、选择对应版本选择下载。 二、安装、设置 1、将下载好的解压。 2、依次打开Apache24-conf-httpd.conf,用记事本打开 1)、修改路径 2)、修改…

mysql去除重复数据

需求描述 doc表有很多重复的title,想去除掉重复的记录 表结构 CREATE TABLE doc (id INT PRIMARY KEY,title VARCHAR(255),content TEXT );去重SQL -- 创建临时表 CREATE TEMPORARY TABLE temp_doc AS SELECT * FROM doc WHERE 10;-- 插入唯一的记录(每个title最…

[数据集][目标检测]红外兔子检测数据集VOC+YOLO格式96张1类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):96 标注数量(xml文件个数):96 标注数量(txt文件个数):96 标注类别数…

Redis 源码学习记录:散列 (dict)

散列 Redis 源码版本:Redis-6.0.9,本篇文章的代码均在 dict.h / dict.c 文件中。 散列类型可以存储一组无需的键值对,他特别适用于存储一个对象数据。 字典 Redis 通常使用字典结构体存储用户散列数据。字典是 Redis 的重要数据结构。除了散…

机械行业工程设计资质乙级需要哪些人员

申请机械行业工程设计资质乙级需要的人员主要包括以下几个方面,具体要求和数量根据参考文章归纳如下: 一、主要专业技术人员 数量要求:主要专业技术人员数量应不少于所申请行业资质标准中主要专业技术人员配备表规定的人数。学历和职称要求…

在虚拟机上安装MySQL和Hive

在虚拟机上安装MySQL和Hive的步骤如下。这里将分别针对MySQL和Hive的安装进行说明。 MySQL安装步骤 1. 准备工作 下载MySQL安装包,选择与你虚拟机操作系统版本相匹配的MySQL版本,例如MySQL 8.0.35。 2. 卸载旧版本(如果已安装&#xff09…

java大学城水电管理系统源码(springboot)

风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的大学城水电管理系统。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 大学城水电管理系统的…

PHP对接百度语音识别技术

PHP对接百度语音识别技术 引言 在目前的各种应用场景中,语音识别技术已经越来越常用,并且其应用场景正在不断扩大。 百度提供的语音识别服务允许用户通过简单的接口调用,将语音内容转换为文本。 本文将通过PHP语言集成百度的语音识别服务…