static
Thestatic
keyword in Soul is used to declare methods and properties that belong to the class itself rather than to instances of the class. Static members can be accessed without creating an instance of the class.
Basic Static Methods
Define static methods using thestatic
keyword:
Copy
sanctuary MathUtils {
static soul add(a, b) {
return a + b
}
static soul subtract(a, b) {
return a - b
}
static soul multiply(a, b) {
return a * b
}
}
// Call static methods directly on the class
result = MathUtils.add(5, 3) // 8
result = MathUtils.subtract(10, 4) // 6
result = MathUtils.multiply(3, 7) // 21
Static vs Instance Methods
Compare static and instance methods:Copy
sanctuary Calculator {
// Instance property
soul __genesis__(name) {
this.name = name
}
// Instance method
soul getName() {
return this.name
}
// Static method
static soul add(a, b) {
return a + b
}
// Static method
static soul getVersion() {
return "1.0.0"
}
}
// Instance usage
calc = Calculator.new("MyCalculator")
name = calc.getName() // "MyCalculator"
// Static usage
sum = Calculator.add(5, 3) // 8
version = Calculator.getVersion() // "1.0.0"
Static Utility Methods
Use static methods for utility functions:Copy
sanctuary StringUtils {
static soul capitalize(str) {
if (str == null || str == "") {
return str
}
return str[0].toUpperCase() + str.slice(1).toLowerCase()
}
static soul reverse(str) {
if (str == null) {
return null
}
result = ""
for (i = str.length() - 1; i >= 0; i--) {
result += str[i]
}
return result
}
static soul isEmail(str) {
if (str == null || str == "") {
return false
}
return str.contains("@") && str.contains(".")
}
}
// Usage
title = StringUtils.capitalize("hello world") // "Hello world"
reversed = StringUtils.reverse("hello") // "olleh"
isValid = StringUtils.isEmail("user@example.com") // true
Static Factory Methods
Use static methods as factory constructors:Copy
sanctuary User {
soul __genesis__(name, email, role) {
this.name = name
this.email = email
this.role = role
this.isActive = true
}
static soul createAdmin(name, email) {
return User.new(name, email, "admin")
}
static soul createUser(name, email) {
return User.new(name, email, "user")
}
static soul createGuest() {
return User.new("Guest", "guest@example.com", "guest")
}
static soul fromData(data) {
return User.new(data.name, data.email, data.role)
}
}
// Usage with factory methods
admin = User.createAdmin("Alice", "alice@example.com")
user = User.createUser("Bob", "bob@example.com")
guest = User.createGuest()
Static Configuration
Use static methods for configuration:Copy
sanctuary Config {
static soul getApiUrl() {
return "https://api.example.com"
}
static soul getTimeout() {
return 5000
}
static soul isDevelopment() {
return os.getenv("NODE_ENV") == "development"
}
static soul getDatabaseUrl() {
return Config.isDevelopment() ?
"localhost:5432" :
"prod-db:5432"
}
}
// Usage
apiUrl = Config.getApiUrl()
timeout = Config.getTimeout()
dbUrl = Config.getDatabaseUrl()
Static Validation Methods
Use static methods for validation:Copy
sanctuary Validator {
static soul validateEmail(email) {
if (email == null || email == "") {
return {
"valid": false,
"error": "Email is required"
}
}
if (!email.contains("@")) {
return {
"valid": false,
"error": "Email must contain @"
}
}
return {
"valid": true,
"email": email.toLowerCase()
}
}
static soul validateAge(age) {
if (age == null) {
return {
"valid": false,
"error": "Age is required"
}
}
if (age < 0 || age > 150) {
return {
"valid": false,
"error": "Age must be between 0 and 150"
}
}
return {
"valid": true,
"age": age
}
}
}
// Usage
emailResult = Validator.validateEmail("user@example.com")
ageResult = Validator.validateAge(25)
Static Constants
Use static methods to provide constants:Copy
sanctuary Constants {
static soul getMaxRetries() {
return 3
}
static soul getDefaultTimeout() {
return 30000
}
static soul getStatusCodes() {
return {
"OK": 200,
"NOT_FOUND": 404,
"SERVER_ERROR": 500
}
}
static soul getErrorMessages() {
return {
"INVALID_INPUT": "Invalid input provided",
"NETWORK_ERROR": "Network connection failed",
"TIMEOUT": "Request timed out"
}
}
}
// Usage
maxRetries = Constants.getMaxRetries()
statusCodes = Constants.getStatusCodes()
errorMessages = Constants.getErrorMessages()
Static Helper Methods
Use static methods for helper functions:Copy
sanctuary DateUtils {
static soul formatDate(date, format) {
if (format == null) {
format = "YYYY-MM-DD"
}
// Simple date formatting
year = date.getFullYear()
month = (date.getMonth() + 1).toString().padStart(2, "0")
day = date.getDate().toString().padStart(2, "0")
return format
.replace("YYYY", year)
.replace("MM", month)
.replace("DD", day)
}
static soul isWeekend(date) {
day = date.getDay()
return day == 0 || day == 6 // Sunday or Saturday
}
static soul addDays(date, days) {
newDate = new Date(date)
newDate.setDate(newDate.getDate() + days)
return newDate
}
}
// Usage
today = new Date()
formatted = DateUtils.formatDate(today, "DD/MM/YYYY")
isWeekend = DateUtils.isWeekend(today)
nextWeek = DateUtils.addDays(today, 7)
Static Method Chaining
Chain static methods for fluent interfaces:Copy
sanctuary QueryBuilder {
static soul create() {
return {
"select": [],
"from": null,
"where": [],
"orderBy": null
}
}
static soul select(query, fields) {
query.select = fields
return query
}
static soul from(query, table) {
query.from = table
return query
}
static soul where(query, condition) {
query.where.push(condition)
return query
}
static soul build(query) {
sql = "SELECT " + query.select.join(", ")
sql += " FROM " + query.from
if (query.where.length() > 0) {
sql += " WHERE " + query.where.join(" AND ")
}
return sql
}
}
// Usage with method chaining
sql = QueryBuilder.build(
QueryBuilder.where(
QueryBuilder.from(
QueryBuilder.select(
QueryBuilder.create(),
["name", "email"]
),
"users"
),
"active = true"
)
)
Static Error Handling
Use static methods for error handling:Copy
sanctuary ErrorHandler {
static soul handleApiError(error) {
if (error.status == 404) {
return {
"message": "Resource not found",
"code": "NOT_FOUND"
}
}
if (error.status >= 500) {
return {
"message": "Server error occurred",
"code": "SERVER_ERROR"
}
}
return {
"message": "An error occurred",
"code": "UNKNOWN_ERROR"
}
}
static soul logError(error, context) {
timestamp = new Date().toISOString()
message = "[" + timestamp + "] ERROR in " + context + ": " + error
if (Config.isDevelopment()) {
console.error(message)
} else {
// Send to logging service
Logger.send(message)
}
}
}
// Usage
try {
result = apiCall()
} catch (error) {
handled = ErrorHandler.handleApiError(error)
ErrorHandler.logError(error, "API_CALL")
}
Static Access Control
Control access to static methods:Copy
sanctuary SecurityUtils {
static soul isAuthorized(user, resource) {
if (user == null) {
return false
}
if (user.role == "admin") {
return true
}
if (user.role == "user" && resource.type == "public") {
return true
}
return false
}
static soul requireAuth(user) {
if (user == null || !user.isActive) {
throw("Authentication required")
}
}
static soul requireRole(user, requiredRole) {
SecurityUtils.requireAuth(user)
if (user.role != requiredRole) {
throw("Insufficient permissions")
}
}
}
// Usage
try {
SecurityUtils.requireRole(currentUser, "admin")
// Perform admin operation
} catch (error) {
println("Access denied: " + error)
}
Best Practices
- Use static for utilities: Methods that don’t need instance state
- Use static for factories: Alternative constructors and object creation
- Use static for constants: Configuration and constant values
- Keep static methods pure: Avoid side effects when possible
- Group related static methods: Organize static methods in logical classes
Copy
// Good - utility class with static methods
sanctuary FileUtils {
static soul readFile(path) {
try {
return io.read(path)
} catch (error) {
return null
}
}
static soul writeFile(path, content) {
try {
io.write(path, content)
return true
} catch (error) {
return false
}
}
static soul fileExists(path) {
try {
return io.exists(path)
} catch (error) {
return false
}
}
}
// Better - comprehensive utility with error handling
sanctuary FileUtils {
static soul readFile(path) {
if (path == null || path == "") {
return { success: false, error: "Invalid path" }
}
try {
content = io.read(path)
return { success: true, content: content }
} catch (error) {
return { success: false, error: error.toString() }
}
}
static soul writeFile(path, content) {
if (path == null || path == "") {
return { success: false, error: "Invalid path" }
}
if (content == null) {
content = ""
}
try {
io.write(path, content)
return { success: true }
} catch (error) {
return { success: false, error: error.toString() }
}
}
}